+
+
+/* ONEWAY ANOVA Calculations */
+
+static void postcalc ( struct cmd_oneway *cmd UNUSED );
+
+static void precalc ( struct cmd_oneway *cmd UNUSED );
+
+int compare_group_id (const struct group_statistics *a,
+ const struct group_statistics *b, int width);
+
+unsigned int hash_group_id(const struct group_statistics *v, int width);
+
+void free_group_id(struct group_statistics *v, void *aux UNUSED);
+
+
+
+
+int
+compare_group_id (const struct group_statistics *a,
+ const struct group_statistics *b, int width)
+{
+ return compare_values(&a->id, &b->id, width);
+}
+
+unsigned int
+hash_group_id(const struct group_statistics *v, int width)
+{
+ return hash_value ( &v->id, width);
+}
+
+void
+free_group_id(struct group_statistics *v, void *aux UNUSED)
+{
+ free(v);
+}
+
+
+/* Pre calculations */
+static void
+precalc ( struct cmd_oneway *cmd UNUSED )
+{
+ int i=0;
+
+ for(i=0; i< n_vars ; ++i)
+ {
+ struct group_statistics *totals = &vars[i]->p.ww.ugs;
+
+ /* Create a hash for each of the dependent variables.
+ The hash contains a group_statistics structure,
+ and is keyed by value of the independent variable */
+
+ vars[i]->p.ww.group_hash =
+ hsh_create(4,
+ (hsh_compare_func *) compare_group_id,
+ (hsh_hash_func *) hash_group_id,
+ (hsh_free_func *) free_group_id,
+ (void *) indep_var->width );
+
+
+ totals->sum=0;
+ totals->n=0;
+ totals->ssq=0;
+ totals->sum_diff=0;
+ totals->maximum = - DBL_MAX;
+ totals->minimum = DBL_MAX;
+ }
+}
+
+
+static void
+calculate(const struct casefile *cf, void *cmd_)
+{
+ struct casereader *r;
+ struct ccase c;
+
+
+ struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
+
+ global_group_hash = hsh_create(4,
+ (hsh_compare_func *) compare_values,
+ (hsh_hash_func *) hash_value,
+ 0,
+ (void *) indep_var->width );
+
+ precalc(cmd);
+
+ for(r = casefile_get_reader (cf);
+ casereader_read (r, &c) ;
+ case_destroy (&c))
+ {
+ int i;
+
+ const double weight =
+ dict_get_case_weight(default_dict,&c,&bad_weight_warn);
+
+ const union value *indep_val = case_data (&c, indep_var->fv);
+
+ hsh_insert ( global_group_hash, (void *) indep_val );
+
+
+ for ( i = 0 ; i < n_vars ; ++i )
+ {
+ const struct variable *v = vars[i];
+
+ const union value *val = case_data (&c, v->fv);
+
+ struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
+
+ struct group_statistics *gs;
+
+ gs = hsh_find(group_hash, (void *) indep_val );
+
+ if ( ! gs )
+ {
+ gs = (struct group_statistics *)
+ xmalloc (sizeof(struct group_statistics));
+
+ gs->id = *indep_val;
+ gs->sum=0;
+ gs->n=0;
+ gs->ssq=0;
+ gs->sum_diff=0;
+ gs->minimum = DBL_MAX;
+ gs->maximum = -DBL_MAX;
+
+ hsh_insert ( group_hash, (void *) gs );
+ }
+
+ if (! value_is_missing(val,v) )
+ {
+ struct group_statistics *totals = &vars[i]->p.ww.ugs;
+
+ totals->n+=weight;
+ totals->sum+=weight * val->f;
+ totals->ssq+=weight * val->f * val->f;
+
+ if ( val->f * weight < totals->minimum )
+ totals->minimum = val->f * weight;
+
+ if ( val->f * weight > totals->maximum )
+ totals->maximum = val->f * weight;
+
+ gs->n+=weight;
+ gs->sum+=weight * val->f;
+ gs->ssq+=weight * val->f * val->f;
+
+ if ( val->f * weight < gs->minimum )
+ gs->minimum = val->f * weight;
+
+ if ( val->f * weight > gs->maximum )
+ gs->maximum = val->f * weight;
+ }
+
+ vars[i]->p.ww.n_groups = hsh_count ( group_hash );
+ }
+
+ }
+ casereader_destroy (r);
+
+ postcalc(cmd);
+
+ ostensible_number_of_groups = hsh_count (global_group_hash);
+
+}
+
+
+/* Post calculations for the ONEWAY command */
+void
+postcalc ( struct cmd_oneway *cmd UNUSED )
+{
+ int i=0;
+
+
+ for(i = 0; i < n_vars ; ++i)
+ {
+ struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
+ struct group_statistics *totals = &vars[i]->p.ww.ugs;
+
+ struct hsh_iterator g;
+ struct group_statistics *gs;
+
+ for (gs = hsh_first (group_hash,&g);
+ gs != 0;
+ gs = hsh_next(group_hash,&g))
+ {
+ gs->mean=gs->sum / gs->n;
+ gs->s_std_dev= sqrt(
+ ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
+ ) ;
+
+ gs->std_dev= sqrt(
+ gs->n/(gs->n-1) *
+ ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
+ ) ;
+
+ gs->se_mean = gs->std_dev / sqrt(gs->n);
+ gs->mean_diff= gs->sum_diff / gs->n;
+
+ }
+
+
+
+ totals->mean = totals->sum / totals->n;
+ totals->std_dev= sqrt(
+ totals->n/(totals->n-1) *
+ ( (totals->ssq / totals->n ) - totals->mean * totals->mean )
+ ) ;
+
+ totals->se_mean = totals->std_dev / sqrt(totals->n);
+
+
+
+
+ }
+}