+ fs->m[v].ptile_hash = list_to_ptile_hash(&percentile_list);
+ fs->m[v].ptile_alg = percentile_algorithm;
+ metrics_postcalc(&fs->m[v]);
+ }
+
+ fctr = fctr->next;
+ }
+
+ totals[v].ptile_hash = list_to_ptile_hash(&percentile_list);
+ totals[v].ptile_alg = percentile_algorithm;
+ metrics_postcalc(&totals[v]);
+ }
+
+
+ /* Make sure that the combination of factors are complete */
+
+ fctr = factors;
+ while ( fctr )
+ {
+ struct hsh_iterator hi;
+ struct hsh_iterator hi0;
+ struct hsh_iterator hi1;
+ struct factor_statistics *fs;
+
+ struct hsh_table *idh0=0;
+ struct hsh_table *idh1=0;
+ union value *val0;
+ union value *val1;
+
+ idh0 = hsh_create(4, (hsh_compare_func *) compare_values,
+ (hsh_hash_func *) hash_value,
+ 0,0);
+
+ idh1 = hsh_create(4, (hsh_compare_func *) compare_values,
+ (hsh_hash_func *) hash_value,
+ 0,0);
+
+
+ for ( fs = hsh_first(fctr->fstats, &hi);
+ fs != 0 ;
+ fs = hsh_next(fctr->fstats, &hi))
+ {
+ hsh_insert(idh0,(void *) &fs->id[0]);
+ hsh_insert(idh1,(void *) &fs->id[1]);
+ }
+
+ /* Ensure that the factors combination is complete */
+ for ( val0 = hsh_first(idh0, &hi0);
+ val0 != 0 ;
+ val0 = hsh_next(idh0, &hi0))
+ {
+ for ( val1 = hsh_first(idh1, &hi1);
+ val1 != 0 ;
+ val1 = hsh_next(idh1, &hi1))
+ {
+ struct factor_statistics **ffs;
+ union value key[2];
+ key[0] = *val0;
+ key[1] = *val1;
+
+ ffs = (struct factor_statistics **)
+ hsh_probe(fctr->fstats, (void *) &key );
+
+ if ( !*ffs ) {
+ int i;
+ (*ffs) = create_factor_statistics (n_dependent_vars,
+ &key[0], &key[1]);
+ for ( i = 0 ; i < n_dependent_vars ; ++i )
+ metrics_precalc( &(*ffs)->m[i]);
+ }
+ }
+ }
+
+ hsh_destroy(idh0);
+ hsh_destroy(idh1);
+
+ fctr->fs = (struct factor_statistics **) hsh_sort_copy(fctr->fstats);
+
+ fctr = fctr->next;
+ }
+
+ output_examine();
+
+
+ if ( totals )
+ {
+ int i;
+ for ( i = 0 ; i < n_dependent_vars ; ++i )
+ {
+ metrics_destroy(&totals[i]);
+ }
+ }
+
+}
+
+
+static void
+show_summary(struct variable **dependent_var, int n_dep_var,
+ const struct factor *fctr)
+{
+ static const char *subtitle[]=
+ {
+ N_("Valid"),
+ N_("Missing"),
+ N_("Total")
+ };
+
+ int i;
+ int heading_columns ;
+ int n_cols;
+ const int heading_rows = 3;
+ struct tab_table *tbl;
+
+ int n_rows ;
+ int n_factors = 1;
+
+ if ( fctr )
+ {
+ heading_columns = 2;
+ n_factors = hsh_count(fctr->fstats);
+ n_rows = n_dep_var * n_factors ;
+
+ if ( fctr->indep_var[1] )
+ heading_columns = 3;
+ }
+ else
+ {
+ heading_columns = 1;
+ n_rows = n_dep_var;
+ }
+
+ n_rows += heading_rows;
+
+ n_cols = heading_columns + 6;
+
+ tbl = tab_create (n_cols,n_rows,0);
+ tab_headers (tbl, heading_columns, 0, heading_rows, 0);
+
+ tab_dim (tbl, tab_natural_dimensions);
+
+ /* Outline the box */
+ tab_box (tbl,
+ TAL_2, TAL_2,
+ -1, -1,
+ 0, 0,
+ n_cols - 1, n_rows - 1);
+
+ /* Vertical lines for the data only */
+ tab_box (tbl,
+ -1, -1,
+ -1, TAL_1,
+ heading_columns, 0,
+ n_cols - 1, n_rows - 1);
+
+
+ tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
+ tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
+ tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, heading_rows -1 );
+
+ tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
+
+
+ tab_title (tbl, 0, _("Case Processing Summary"));
+
+
+ tab_joint_text(tbl, heading_columns, 0,
+ n_cols -1, 0,
+ TAB_CENTER | TAT_TITLE,
+ _("Cases"));
+
+ /* Remove lines ... */
+ tab_box (tbl,
+ -1, -1,
+ TAL_0, TAL_0,
+ heading_columns, 0,
+ n_cols - 1, 0);
+
+ for ( i = 0 ; i < 3 ; ++i )
+ {
+ tab_text (tbl, heading_columns + i*2 , 2, TAB_CENTER | TAT_TITLE,
+ _("N"));
+
+ tab_text (tbl, heading_columns + i*2 + 1, 2, TAB_CENTER | TAT_TITLE,
+ _("Percent"));
+
+ tab_joint_text(tbl, heading_columns + i*2 , 1,
+ heading_columns + i*2 + 1, 1,
+ TAB_CENTER | TAT_TITLE,
+ subtitle[i]);
+
+ tab_box (tbl, -1, -1,
+ TAL_0, TAL_0,
+ heading_columns + i*2, 1,
+ heading_columns + i*2 + 1, 1);
+
+ }
+
+
+ /* Titles for the independent variables */
+ if ( fctr )
+ {
+ tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[0]));
+
+ if ( fctr->indep_var[1] )
+ {
+ tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[1]));
+ }
+
+ }
+
+
+ for ( i = 0 ; i < n_dep_var ; ++i )
+ {
+ int n_factors = 1;
+ if ( fctr )
+ n_factors = hsh_count(fctr->fstats);
+
+
+ if ( i > 0 )
+ tab_hline(tbl, TAL_1, 0, n_cols -1 , i * n_factors + heading_rows);
+
+ tab_text (tbl,
+ 0, i * n_factors + heading_rows,
+ TAB_LEFT | TAT_TITLE,
+ var_to_string(dependent_var[i])
+ );
+
+
+ if ( !fctr )
+ populate_summary(tbl, heading_columns,
+ (i * n_factors) + heading_rows,
+ &totals[i]);
+
+
+ else
+ {
+ struct factor_statistics **fs = fctr->fs;
+ int count = 0 ;
+
+ while (*fs)
+ {
+ static union value prev;
+
+ if ( 0 != compare_values(&prev, &(*fs)->id[0],
+ fctr->indep_var[0]->width))
+ {
+ tab_text (tbl,
+ 1,
+ (i * n_factors ) + count +
+ heading_rows,
+ TAB_LEFT | TAT_TITLE,
+ value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+ );
+
+ if (fctr->indep_var[1] && count > 0 )
+ tab_hline(tbl, TAL_1, 1, n_cols - 1,
+ (i * n_factors ) + count + heading_rows);
+