1 /* PSPP - EXAMINE data for normality . -*-c-*-
3 Copyright (C) 2004 Free Software Foundation, Inc.
4 Author: John Darrington 2004
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include <gsl/gsl_cdf.h>
37 #include "value-labels.h"
42 #include "factor_stats.h"
49 +missing=miss:pairwise/!listwise,
51 incl:include/!exclude;
52 +compare=cmp:variables/!groups;
53 +plot[plt_]=stemleaf,boxplot,npplot,:spreadlevel(*d:n),histogram,all,none;
55 +statistics[st_]=descriptives,:extreme(*d:n),all,none.
64 static struct cmd_examine cmd;
66 static struct variable **dependent_vars;
68 static int n_dependent_vars;
70 static struct hsh_table *hash_table_factors;
77 /* The independent variable for this factor */
78 struct variable *indep_var;
80 /* The factor statistics for each value of the independent variable */
81 struct hsh_table *hash_table_val;
83 /* The subfactor (if any) */
84 struct factor *subfactor;
91 /* Parse the clause specifying the factors */
92 static int examine_parse_independent_vars(struct cmd_examine *cmd,
93 struct hsh_table *hash_factors );
98 /* Functions to support hashes of factors */
99 int compare_factors(const struct factor *f1, const struct factor *f2,
102 unsigned hash_factor(const struct factor *f, void *aux);
104 void free_factor(struct factor *f, void *aux UNUSED);
107 /* Output functions */
108 static void show_summary(struct variable **dependent_var, int n_dep_var,
111 static void show_descriptives(struct variable **dependent_var,
113 struct factor *factor);
116 static void show_extremes(struct variable **dependent_var,
118 struct factor *factor,
122 /* Per Split function */
123 static void run_examine(const struct casefile *cf, void *cmd_);
125 static void output_examine(void);
128 static struct factor_statistics *totals = 0;
136 if ( !parse_examine(&cmd) )
139 if ( cmd.st_n == SYSMIS )
142 if ( ! cmd.sbc_cinterval)
143 cmd.n_cinterval[0] = 95.0;
146 totals = xmalloc ( sizeof (struct factor_statistics *) );
148 totals->stats = xmalloc(sizeof ( struct metrics ) * n_dependent_vars);
150 multipass_procedure_with_splits (run_examine, &cmd);
153 hsh_destroy(hash_table_factors);
162 /* Show all the appropriate tables */
167 /* Show totals if appropriate */
168 if ( ! cmd.sbc_nototal ||
169 ! hash_table_factors || 0 == hsh_count (hash_table_factors))
171 show_summary(dependent_vars, n_dependent_vars,0);
173 if ( cmd.sbc_statistics )
175 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES])
176 show_descriptives(dependent_vars, n_dependent_vars, 0);
178 if ( cmd.a_statistics[XMN_ST_EXTREME])
179 show_extremes(dependent_vars, n_dependent_vars, 0, cmd.st_n);
183 /* Show grouped statistics if appropriate */
184 if ( hash_table_factors && 0 != hsh_count (hash_table_factors))
186 struct hsh_iterator hi;
189 for(f = hsh_first(hash_table_factors,&hi);
191 f = hsh_next(hash_table_factors,&hi))
193 show_summary(dependent_vars, n_dependent_vars,f);
195 if ( cmd.sbc_statistics )
197 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES])
198 show_descriptives(dependent_vars, n_dependent_vars, f);
200 if ( cmd.a_statistics[XMN_ST_EXTREME])
201 show_extremes(dependent_vars, n_dependent_vars, f, cmd.st_n);
211 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
213 xmn_custom_total(struct cmd_examine *p)
215 if ( p->sbc_nototal )
217 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
225 xmn_custom_nototal(struct cmd_examine *p)
229 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
237 /* Compare two factors */
239 compare_factors (const struct factor *f1,
240 const struct factor *f2,
243 int indep_var_cmp = strcmp(f1->indep_var->name, f2->indep_var->name);
245 if ( 0 != indep_var_cmp )
246 return indep_var_cmp;
248 /* If the names are identical, and there are no subfactors then
249 the factors are identical */
250 if ( ! f1->subfactor && ! f2->subfactor )
253 /* ... otherwise we must compare the subfactors */
255 return compare_factors(f1->subfactor, f2->subfactor, aux);
259 /* Create a hash of a factor */
261 hash_factor( const struct factor *f, void *aux)
264 h = hsh_hash_string(f->indep_var->name);
267 h += hash_factor(f->subfactor, aux);
273 /* Free up a factor */
275 free_factor(struct factor *f, void *aux)
277 hsh_destroy(f->hash_table_val);
280 free_factor(f->subfactor, aux);
286 /* Parser for the variables sub command */
288 xmn_custom_variables(struct cmd_examine *cmd )
293 if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
297 if (!parse_variables (default_dict, &dependent_vars, &n_dependent_vars,
298 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
300 free (dependent_vars);
304 assert(n_dependent_vars);
306 if ( lex_match(T_BY))
308 hash_table_factors = hsh_create(4,
309 (hsh_compare_func *) compare_factors,
310 (hsh_hash_func *) hash_factor,
311 (hsh_free_func *) free_factor, 0);
313 return examine_parse_independent_vars(cmd, hash_table_factors);
322 /* Parse the clause specifying the factors */
324 examine_parse_independent_vars(struct cmd_examine *cmd,
325 struct hsh_table *hash_table_factors )
327 struct factor *f = 0;
329 if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
335 f = xmalloc(sizeof(struct factor));
337 f->hash_table_val = 0;
341 f->indep_var = parse_variable();
343 if ( ! f->hash_table_val )
344 f->hash_table_val = hsh_create(4,(hsh_compare_func *) compare_indep_values,
345 (hsh_hash_func *) hash_indep_value,
346 (hsh_free_func *) free_factor_stats,
347 (void *) f->indep_var->width);
353 if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
357 f->subfactor = xmalloc(sizeof(struct factor));
359 f->subfactor->indep_var = parse_variable();
361 f->subfactor->subfactor = 0;
363 f->subfactor->hash_table_val =
365 (hsh_compare_func *) compare_indep_values,
366 (hsh_hash_func *) hash_indep_value,
367 (hsh_free_func *) free_factor_stats,
368 (void *) f->subfactor->indep_var->width);
371 hsh_insert(hash_table_factors, f);
375 if ( token == '.' || token == '/' )
378 return examine_parse_independent_vars(cmd, hash_table_factors);
382 void populate_descriptives(struct tab_table *t, int col, int row,
383 const struct metrics *fs);
386 void populate_extremities(struct tab_table *t, int col, int row, int n);
389 /* Show the descriptives table */
391 show_descriptives(struct variable **dependent_var,
393 struct factor *factor)
396 int heading_columns ;
398 const int n_stat_rows = 13;
400 const int heading_rows = 1;
401 int n_rows = heading_rows ;
409 n_rows += n_dep_var * n_stat_rows;
413 assert(factor->indep_var);
414 if ( factor->subfactor == 0 )
417 n_rows += n_dep_var * hsh_count(factor->hash_table_val) * n_stat_rows;
422 n_rows += n_dep_var * hsh_count(factor->hash_table_val) *
423 hsh_count(factor->subfactor->hash_table_val) * n_stat_rows ;
427 n_cols = heading_columns + 4;
429 t = tab_create (n_cols, n_rows, 0);
431 tab_headers (t, heading_columns + 1, 0, heading_rows, 0);
433 tab_dim (t, tab_natural_dimensions);
435 /* Outline the box and have no internal lines*/
440 n_cols - 1, n_rows - 1);
442 tab_hline (t, TAL_2, 0, n_cols - 1, heading_rows );
444 tab_vline (t, TAL_1, heading_columns, 0, n_rows - 1);
445 tab_vline (t, TAL_2, n_cols - 2, 0, n_rows - 1);
446 tab_vline (t, TAL_1, n_cols - 1, 0, n_rows - 1);
448 tab_text (t, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Statistic"));
449 tab_text (t, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
452 for ( i = 0 ; i < n_dep_var ; ++i )
455 int n_subfactors = 1;
460 n_factors = hsh_count(factor->hash_table_val);
461 if ( factor->subfactor )
462 n_subfactors = hsh_count(factor->subfactor->hash_table_val);
466 row = heading_rows + i * n_stat_rows * n_factors * n_subfactors;
469 tab_hline(t, TAL_1, 0, n_cols - 1, row );
473 struct hsh_iterator hi;
474 const struct factor_statistics *fs;
477 tab_text (t, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
478 var_to_string(factor->indep_var));
482 for (fs = hsh_first(factor->hash_table_val, &hi);
484 fs = hsh_next(factor->hash_table_val, &hi))
487 row + count * n_subfactors * n_stat_rows,
488 TAB_RIGHT | TAT_TITLE,
489 value_to_string(fs->id, factor->indep_var)
493 tab_hline (t, TAL_1, 1, n_cols - 1,
494 row + count * n_subfactors * n_stat_rows);
496 if ( factor->subfactor )
499 struct hsh_iterator h2;
500 const struct factor_statistics *sub_fs;
502 tab_text (t, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
503 var_to_string(factor->subfactor->indep_var));
505 for ( sub_fs = hsh_first(factor->subfactor->hash_table_val,
508 sub_fs = hsh_next(factor->subfactor->hash_table_val,
514 + count * n_subfactors * n_stat_rows
515 + count2 * n_stat_rows,
516 TAB_RIGHT | TAT_TITLE ,
517 value_to_string(sub_fs->id, factor->subfactor->indep_var)
521 tab_hline (t, TAL_1, 2, n_cols - 1,
523 + count * n_subfactors * n_stat_rows
524 + count2 * n_stat_rows);
526 populate_descriptives(t, heading_columns,
528 + count * n_subfactors
530 + count2 * n_stat_rows,
540 populate_descriptives(t, heading_columns,
542 + count * n_subfactors * n_stat_rows,
551 populate_descriptives(t, heading_columns,
552 row, &totals->stats[i]);
557 TAB_LEFT | TAT_TITLE,
558 var_to_string(dependent_var[i])
563 tab_title (t, 0, _("Descriptives"));
571 /* Fill in the descriptives data */
573 populate_descriptives(struct tab_table *tbl, int col, int row,
574 const struct metrics *m)
577 const double t = gsl_cdf_tdist_Qinv(1 - cmd.n_cinterval[0]/100.0/2.0, \
583 TAB_LEFT | TAT_TITLE,
586 tab_float (tbl, col + 2,
592 tab_float (tbl, col + 3,
601 TAB_LEFT | TAT_TITLE | TAT_PRINTF,
602 _("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
605 tab_text (tbl, col + 1,
607 TAB_LEFT | TAT_TITLE,
610 tab_float (tbl, col + 2,
613 m->mean - t * m->stderr,
616 tab_text (tbl, col + 1,
618 TAB_LEFT | TAT_TITLE,
622 tab_float (tbl, col + 2,
625 m->mean + t * m->stderr,
630 TAB_LEFT | TAT_TITLE,
631 _("5% Trimmed Mean"));
635 TAB_LEFT | TAT_TITLE,
640 TAB_LEFT | TAT_TITLE,
643 tab_float (tbl, col + 2,
652 TAB_LEFT | TAT_TITLE,
653 _("Std. Deviation"));
656 tab_float (tbl, col + 2,
665 TAB_LEFT | TAT_TITLE,
668 tab_float (tbl, col + 2,
676 TAB_LEFT | TAT_TITLE,
679 tab_float (tbl, col + 2,
688 TAB_LEFT | TAT_TITLE,
692 tab_float (tbl, col + 2,
700 TAB_LEFT | TAT_TITLE,
701 _("Interquartile Range"));
705 TAB_LEFT | TAT_TITLE,
710 TAB_LEFT | TAT_TITLE,
716 show_summary(struct variable **dependent_var,
718 struct factor *factor)
720 static const char *subtitle[]=
728 int heading_columns ;
730 const int heading_rows = 3;
731 struct tab_table *tbl;
733 int n_rows = heading_rows;
742 assert(factor->indep_var);
743 if ( factor->subfactor == 0 )
746 n_rows += n_dep_var * hsh_count(factor->hash_table_val);
751 n_rows += n_dep_var * hsh_count(factor->hash_table_val) *
752 hsh_count(factor->subfactor->hash_table_val) ;
757 n_cols = heading_columns + 6;
759 tbl = tab_create (n_cols,n_rows,0);
760 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
762 tab_dim (tbl, tab_natural_dimensions);
764 /* Outline the box and have vertical internal lines*/
769 n_cols - 1, n_rows - 1);
771 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
772 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
773 tab_hline (tbl, TAL_1, 0, n_cols - 1, heading_rows -1 );
775 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
778 tab_title (tbl, 0, _("Case Processing Summary"));
781 tab_joint_text(tbl, heading_columns, 0,
783 TAB_CENTER | TAT_TITLE,
786 /* Remove lines ... */
795 tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
796 var_to_string(factor->indep_var));
798 if ( factor->subfactor )
799 tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
800 var_to_string(factor->subfactor->indep_var));
803 for ( i = 0 ; i < 3 ; ++i )
805 tab_text (tbl, heading_columns + i*2 , 2, TAB_CENTER | TAT_TITLE, _("N"));
806 tab_text (tbl, heading_columns + i*2 + 1, 2, TAB_CENTER | TAT_TITLE,
809 tab_joint_text(tbl, heading_columns + i*2 , 1,
810 heading_columns + i*2 + 1, 1,
811 TAB_CENTER | TAT_TITLE,
814 tab_box (tbl, -1, -1,
816 heading_columns + i*2, 1,
817 heading_columns + i*2 + 1, 1);
822 for ( i = 0 ; i < n_dep_var ; ++i )
824 int n_subfactors = 1;
829 n_factors = hsh_count(factor->hash_table_val);
830 if ( factor->subfactor )
831 n_subfactors = hsh_count(factor->subfactor->hash_table_val);
835 0, i * n_factors * n_subfactors + heading_rows,
836 TAB_LEFT | TAT_TITLE,
837 var_to_string(dependent_var[i])
842 struct hsh_iterator hi;
843 const struct factor_statistics *fs;
846 for (fs = hsh_first(factor->hash_table_val, &hi);
848 fs = hsh_next(factor->hash_table_val, &hi))
851 i * n_factors * n_subfactors + heading_rows
852 + count * n_subfactors,
853 TAB_RIGHT | TAT_TITLE,
854 value_to_string(fs->id, factor->indep_var)
857 if ( factor->subfactor )
860 struct hsh_iterator h2;
861 const struct factor_statistics *sub_fs;
863 for ( sub_fs = hsh_first(factor->subfactor->hash_table_val,
866 sub_fs = hsh_next(factor->subfactor->hash_table_val,
871 i * n_factors * n_subfactors + heading_rows
872 + count * n_subfactors + count2,
873 TAB_RIGHT | TAT_TITLE ,
874 value_to_string(sub_fs->id, factor->subfactor->indep_var)
890 static int bad_weight_warn = 1;
894 run_examine(const struct casefile *cf, void *cmd_)
896 struct hsh_iterator hi;
899 struct casereader *r;
903 const struct cmd_examine *cmd = (struct cmd_examine *) cmd_;
905 /* Make sure we haven't got rubbish left over from a
907 if ( hash_table_factors )
909 for ( fctr = hsh_first(hash_table_factors, &hi);
911 fctr = hsh_next (hash_table_factors, &hi) )
913 hsh_clear(fctr->hash_table_val);
915 while ( (fctr = fctr->subfactor) )
916 hsh_clear(fctr->hash_table_val);
920 for ( v = 0 ; v < n_dependent_vars ; ++v )
921 metrics_precalc(&totals->stats[v]);
923 for(r = casefile_get_reader (cf);
924 casereader_read (r, &c) ;
927 const double weight =
928 dict_get_case_weight(default_dict, &c, &bad_weight_warn);
930 for ( v = 0 ; v < n_dependent_vars ; ++v )
932 const struct variable *var = dependent_vars[v];
933 const union value *val = case_data (&c, var->fv);
935 metrics_calc(&totals->stats[v], val->f, weight);
938 if ( hash_table_factors )
940 for ( fctr = hsh_first(hash_table_factors, &hi);
942 fctr = hsh_next (hash_table_factors, &hi) )
944 const union value *indep_val =
945 case_data(&c, fctr->indep_var->fv);
947 struct factor_statistics **foo = ( struct factor_statistics ** )
948 hsh_probe(fctr->hash_table_val, (void *) &indep_val);
952 *foo = xmalloc ( sizeof ( struct factor_statistics));
953 (*foo)->id = indep_val;
954 (*foo)->stats = xmalloc ( sizeof ( struct metrics )
957 for ( v = 0 ; v < n_dependent_vars ; ++v )
958 metrics_precalc( &(*foo)->stats[v] );
960 hsh_insert(fctr->hash_table_val, (void *) *foo);
963 for ( v = 0 ; v < n_dependent_vars ; ++v )
965 const struct variable *var = dependent_vars[v];
966 const union value *val = case_data (&c, var->fv);
968 metrics_calc( &(*foo)->stats[v], val->f, weight );
971 if ( fctr->subfactor )
973 struct factor *sfctr = fctr->subfactor;
975 const union value *ii_val =
976 case_data (&c, sfctr->indep_var->fv);
978 struct factor_statistics **bar =
979 (struct factor_statistics **)
980 hsh_probe(sfctr->hash_table_val, (void *) &ii_val);
984 *bar = xmalloc ( sizeof ( struct factor_statistics));
986 (*bar)->stats = xmalloc ( sizeof ( struct metrics )
989 for ( v = 0 ; v < n_dependent_vars ; ++v )
990 metrics_precalc( &(*bar)->stats[v] );
992 hsh_insert(sfctr->hash_table_val,
996 for ( v = 0 ; v < n_dependent_vars ; ++v )
998 const struct variable *var = dependent_vars[v];
999 const union value *val = case_data (&c, var->fv);
1001 metrics_calc( &(*bar)->stats[v], val->f, weight );
1009 for ( v = 0 ; v < n_dependent_vars ; ++v)
1011 for ( fctr = hsh_first(hash_table_factors, &hi);
1013 fctr = hsh_next (hash_table_factors, &hi) )
1015 struct hsh_iterator h2;
1016 struct factor_statistics *fs;
1018 for ( fs = hsh_first(fctr->hash_table_val,&h2);
1020 fs = hsh_next(fctr->hash_table_val,&h2))
1022 metrics_postcalc( &fs->stats[v] );
1025 if ( fctr->subfactor)
1027 struct hsh_iterator hsf;
1028 struct factor_statistics *fss;
1030 for ( fss = hsh_first(fctr->subfactor->hash_table_val,&hsf);
1032 fss = hsh_next(fctr->subfactor->hash_table_val,&hsf))
1034 metrics_postcalc( &fss->stats[v] );
1039 metrics_postcalc(&totals->stats[v]);
1048 show_extremes(struct variable **dependent_var,
1050 struct factor *factor,
1054 int heading_columns ;
1056 const int heading_rows = 1;
1057 struct tab_table *t;
1059 int n_rows = heading_rows;
1063 heading_columns = 1 + 1;
1064 n_rows += n_dep_var * 2 * n_extremities;
1068 assert(factor->indep_var);
1069 if ( factor->subfactor == 0 )
1071 heading_columns = 2 + 1;
1072 n_rows += n_dep_var * 2 * n_extremities
1073 * hsh_count(factor->hash_table_val);
1077 heading_columns = 3 + 1;
1078 n_rows += n_dep_var * 2 * n_extremities
1079 * hsh_count(factor->hash_table_val)
1080 * hsh_count(factor->subfactor->hash_table_val) ;
1085 n_cols = heading_columns + 3;
1087 t = tab_create (n_cols,n_rows,0);
1088 tab_headers (t, heading_columns, 0, heading_rows, 0);
1090 tab_dim (t, tab_natural_dimensions);
1092 /* Outline the box and have vertical internal lines*/
1097 n_cols - 1, n_rows - 1);
1101 tab_hline (t, TAL_2, 0, n_cols - 1, heading_rows );
1103 tab_title (t, 0, _("Extreme Values"));
1108 /* Remove lines ... */
1117 tab_text (t, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1118 var_to_string(factor->indep_var));
1120 if ( factor->subfactor )
1121 tab_text (t, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1122 var_to_string(factor->subfactor->indep_var));
1125 tab_text (t, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Value"));
1126 tab_text (t, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Case Number"));
1129 for ( i = 0 ; i < n_dep_var ; ++i )
1131 int n_subfactors = 1;
1136 n_factors = hsh_count(factor->hash_table_val);
1137 if ( factor->subfactor )
1138 n_subfactors = hsh_count(factor->subfactor->hash_table_val);
1142 0, i * 2 * n_extremities * n_factors *
1143 n_subfactors + heading_rows,
1144 TAB_LEFT | TAT_TITLE,
1145 var_to_string(dependent_var[i])
1151 TAL_1, 0, n_cols - 1,
1152 heading_rows + 2 * n_extremities *
1153 (i * n_factors * n_subfactors )
1158 struct hsh_iterator hi;
1159 const struct factor_statistics *fs;
1162 for ( fs = hsh_first(factor->hash_table_val, &hi);
1164 fs = hsh_next(factor->hash_table_val, &hi))
1166 tab_text (t, 1, heading_rows + 2 * n_extremities *
1167 (i * n_factors * n_subfactors
1168 + count * n_subfactors),
1169 TAB_RIGHT | TAT_TITLE,
1170 value_to_string(fs->id, factor->indep_var)
1174 tab_hline (t, TAL_1, 1, n_cols - 1,
1175 heading_rows + 2 * n_extremities *
1176 (i * n_factors * n_subfactors
1177 + count * n_subfactors));
1180 if ( factor->subfactor )
1182 struct hsh_iterator h2;
1183 const struct factor_statistics *sub_fs;
1186 for ( sub_fs = hsh_first(factor->subfactor->hash_table_val,
1189 sub_fs = hsh_next(factor->subfactor->hash_table_val,
1193 tab_text(t, 2, heading_rows + 2 * n_extremities *
1194 (i * n_factors * n_subfactors
1195 + count * n_subfactors + count2 ),
1196 TAB_RIGHT | TAT_TITLE ,
1197 value_to_string(sub_fs->id,
1198 factor->subfactor->indep_var)
1203 tab_hline (t, TAL_1, 2, n_cols - 1,
1204 heading_rows + 2 * n_extremities *
1205 (i * n_factors * n_subfactors
1206 + count * n_subfactors + count2 ));
1208 populate_extremities(t,3,
1209 heading_rows + 2 * n_extremities *
1210 (i * n_factors * n_subfactors
1211 + count * n_subfactors + count2),
1219 populate_extremities(t,2,
1220 heading_rows + 2 * n_extremities *
1221 (i * n_factors * n_subfactors
1222 + count * n_subfactors),
1231 populate_extremities(t, 1,
1232 heading_rows + 2 * n_extremities *
1233 (i * n_factors * n_subfactors ),
1244 /* Fill in the extremities table */
1246 populate_extremities(struct tab_table *t, int col, int row, int n)
1250 tab_text(t, col, row,
1251 TAB_RIGHT | TAT_TITLE ,
1255 tab_text(t, col, row + n ,
1256 TAB_RIGHT | TAT_TITLE ,
1260 for (i = 0; i < n ; ++i )
1262 tab_float(t, col + 1, row + i,
1266 tab_float(t, col + 1, row + i + n,