1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2010, 2011, 2013, 2015, 2016 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "data/casegrouper.h"
22 #include "data/casereader.h"
23 #include "data/dataset.h"
24 #include "data/dictionary.h"
25 #include "data/format.h"
26 #include "data/missing-values.h"
27 #include "language/command.h"
28 #include "language/lexer/lexer.h"
29 #include "language/lexer/variable-parser.h"
30 #include "libpspp/message.h"
31 #include "libpspp/misc.h"
32 #include "libpspp/str.h"
33 #include "math/moments.h"
34 #include "output/tab.h"
35 #include "output/text-item.h"
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) msgid
43 const struct variable
**items
;
46 double sum_of_variances
;
47 double variance_of_sums
;
48 int totals_idx
; /* Casereader index into the totals */
50 struct moments1
**m
; /* Moments of the items */
51 struct moments1
*total
; /* Moments of the totals */
56 dump_cronbach (const struct cronbach
*s
)
59 printf ("N items %d\n", s
->n_items
);
60 for (i
= 0 ; i
< s
->n_items
; ++i
)
62 printf ("%s\n", var_get_name (s
->items
[i
]));
65 printf ("Totals idx %d\n", s
->totals_idx
);
67 printf ("scale variance %g\n", s
->variance_of_sums
);
68 printf ("alpha %g\n", s
->alpha
);
82 SUMMARY_TOTAL
= 0x0001,
88 const struct variable
**variables
;
90 enum mv_class exclude
;
97 struct string scale_name
;
103 enum summary_opts summary
;
105 const struct variable
*wv
;
109 static bool run_reliability (struct dataset
*ds
, const struct reliability
*reliability
);
112 reliability_destroy (struct reliability
*rel
)
115 ds_destroy (&rel
->scale_name
);
117 for (j
= 0; j
< rel
->n_sc
; ++j
)
120 free (rel
->sc
[j
].items
);
121 moments1_destroy (rel
->sc
[j
].total
);
123 for (x
= 0; x
< rel
->sc
[j
].n_items
; ++x
)
124 free (rel
->sc
[j
].m
[x
]);
129 free (rel
->variables
);
133 cmd_reliability (struct lexer
*lexer
, struct dataset
*ds
)
135 const struct dictionary
*dict
= dataset_dict (ds
);
137 struct reliability reliability
;
138 reliability
.n_variables
= 0;
139 reliability
.variables
= NULL
;
140 reliability
.model
= MODEL_ALPHA
;
141 reliability
.exclude
= MV_ANY
;
142 reliability
.summary
= 0;
143 reliability
.n_sc
= 0;
144 reliability
.sc
= NULL
;
145 reliability
.wv
= dict_get_weight (dict
);
146 reliability
.total_start
= 0;
147 ds_init_empty (&reliability
.scale_name
);
150 lex_match (lexer
, T_SLASH
);
152 if (!lex_force_match_id (lexer
, "VARIABLES"))
157 lex_match (lexer
, T_EQUALS
);
159 if (!parse_variables_const (lexer
, dict
, &reliability
.variables
, &reliability
.n_variables
,
160 PV_NO_DUPLICATE
| PV_NUMERIC
))
163 if (reliability
.n_variables
< 2)
164 msg (MW
, _("Reliability on a single variable is not useful."));
170 /* Create a default Scale */
172 reliability
.n_sc
= 1;
173 reliability
.sc
= xzalloc (sizeof (struct cronbach
) * reliability
.n_sc
);
175 ds_assign_cstr (&reliability
.scale_name
, "ANY");
177 c
= &reliability
.sc
[0];
178 c
->n_items
= reliability
.n_variables
;
179 c
->items
= xzalloc (sizeof (struct variable
*) * c
->n_items
);
181 for (i
= 0 ; i
< c
->n_items
; ++i
)
182 c
->items
[i
] = reliability
.variables
[i
];
187 while (lex_token (lexer
) != T_ENDCMD
)
189 lex_match (lexer
, T_SLASH
);
191 if (lex_match_id (lexer
, "SCALE"))
193 struct const_var_set
*vs
;
194 if ( ! lex_force_match (lexer
, T_LPAREN
))
197 if ( ! lex_force_string (lexer
) )
200 ds_assign_substring (&reliability
.scale_name
, lex_tokss (lexer
));
204 if ( ! lex_force_match (lexer
, T_RPAREN
))
207 lex_match (lexer
, T_EQUALS
);
209 vs
= const_var_set_create_from_array (reliability
.variables
, reliability
.n_variables
);
211 free (reliability
.sc
->items
);
212 if (!parse_const_var_set_vars (lexer
, vs
, &reliability
.sc
->items
, &reliability
.sc
->n_items
, 0))
214 const_var_set_destroy (vs
);
218 const_var_set_destroy (vs
);
220 else if (lex_match_id (lexer
, "MODEL"))
222 lex_match (lexer
, T_EQUALS
);
223 if (lex_match_id (lexer
, "ALPHA"))
225 reliability
.model
= MODEL_ALPHA
;
227 else if (lex_match_id (lexer
, "SPLIT"))
229 reliability
.model
= MODEL_SPLIT
;
230 reliability
.split_point
= -1;
232 if ( lex_match (lexer
, T_LPAREN
)
233 && lex_force_num (lexer
))
235 reliability
.split_point
= lex_number (lexer
);
237 if (! lex_force_match (lexer
, T_RPAREN
))
244 else if (lex_match_id (lexer
, "SUMMARY"))
246 lex_match (lexer
, T_EQUALS
);
247 if (lex_match_id (lexer
, "TOTAL"))
249 reliability
.summary
|= SUMMARY_TOTAL
;
251 else if (lex_match (lexer
, T_ALL
))
253 reliability
.summary
= 0xFFFF;
258 else if (lex_match_id (lexer
, "MISSING"))
260 lex_match (lexer
, T_EQUALS
);
261 while (lex_token (lexer
) != T_ENDCMD
&& lex_token (lexer
) != T_SLASH
)
263 if (lex_match_id (lexer
, "INCLUDE"))
265 reliability
.exclude
= MV_SYSTEM
;
267 else if (lex_match_id (lexer
, "EXCLUDE"))
269 reliability
.exclude
= MV_ANY
;
273 lex_error (lexer
, NULL
);
278 else if (lex_match_id (lexer
, "STATISTICS"))
280 lex_match (lexer
, T_EQUALS
);
281 msg (SW
, _("The STATISTICS subcommand is not yet implemented. "
282 "No statistics will be produced."));
283 while (lex_match (lexer
, T_ID
))
288 lex_error (lexer
, NULL
);
293 if ( reliability
.model
== MODEL_SPLIT
)
296 const struct cronbach
*s
;
298 if ( reliability
.split_point
>= reliability
.n_variables
)
300 msg (ME
, _("The split point must be less than the number of variables"));
304 reliability
.n_sc
+= 2 ;
305 reliability
.sc
= xrealloc (reliability
.sc
, sizeof (struct cronbach
) * reliability
.n_sc
);
307 s
= &reliability
.sc
[0];
309 reliability
.sc
[1].n_items
=
310 (reliability
.split_point
== -1) ? s
->n_items
/ 2 : reliability
.split_point
;
312 reliability
.sc
[2].n_items
= s
->n_items
- reliability
.sc
[1].n_items
;
313 reliability
.sc
[1].items
= xzalloc (sizeof (struct variable
*)
314 * reliability
.sc
[1].n_items
);
316 reliability
.sc
[2].items
= xzalloc (sizeof (struct variable
*) *
317 reliability
.sc
[2].n_items
);
319 for (i
= 0; i
< reliability
.sc
[1].n_items
; ++i
)
320 reliability
.sc
[1].items
[i
] = s
->items
[i
];
322 while (i
< s
->n_items
)
324 reliability
.sc
[2].items
[i
- reliability
.sc
[1].n_items
] = s
->items
[i
];
329 if ( reliability
.summary
& SUMMARY_TOTAL
)
332 const int base_sc
= reliability
.n_sc
;
334 reliability
.total_start
= base_sc
;
336 reliability
.n_sc
+= reliability
.sc
[0].n_items
;
337 reliability
.sc
= xrealloc (reliability
.sc
, sizeof (struct cronbach
) * reliability
.n_sc
);
340 for (i
= 0 ; i
< reliability
.sc
[0].n_items
; ++i
)
344 struct cronbach
*s
= &reliability
.sc
[i
+ base_sc
];
346 s
->n_items
= reliability
.sc
[0].n_items
- 1;
347 s
->items
= xzalloc (sizeof (struct variable
*) * s
->n_items
);
348 for (v_src
= 0 ; v_src
< reliability
.sc
[0].n_items
; ++v_src
)
351 s
->items
[v_dest
++] = reliability
.sc
[0].items
[v_src
];
357 if ( ! run_reliability (ds
, &reliability
))
360 reliability_destroy (&reliability
);
364 reliability_destroy (&reliability
);
370 do_reliability (struct casereader
*group
, struct dataset
*ds
,
371 const struct reliability
*rel
);
374 static void reliability_summary_total (const struct reliability
*rel
);
376 static void reliability_statistics (const struct reliability
*rel
);
380 run_reliability (struct dataset
*ds
, const struct reliability
*reliability
)
382 struct dictionary
*dict
= dataset_dict (ds
);
384 struct casereader
*group
;
386 struct casegrouper
*grouper
= casegrouper_create_splits (proc_open (ds
), dict
);
389 for (si
= 0 ; si
< reliability
->n_sc
; ++si
)
391 struct cronbach
*s
= &reliability
->sc
[si
];
394 s
->m
= xzalloc (sizeof *s
->m
* s
->n_items
);
395 s
->total
= moments1_create (MOMENT_VARIANCE
);
397 for (i
= 0 ; i
< s
->n_items
; ++i
)
398 s
->m
[i
] = moments1_create (MOMENT_VARIANCE
);
402 while (casegrouper_get_next_group (grouper
, &group
))
404 do_reliability (group
, ds
, reliability
);
406 reliability_statistics (reliability
);
408 if (reliability
->summary
& SUMMARY_TOTAL
)
409 reliability_summary_total (reliability
);
412 ok
= casegrouper_destroy (grouper
);
413 ok
= proc_commit (ds
) && ok
;
422 /* Return the sum of all the item variables in S */
424 append_sum (const struct ccase
*c
, casenumber n UNUSED
, void *aux
)
427 const struct cronbach
*s
= aux
;
430 for (v
= 0 ; v
< s
->n_items
; ++v
)
432 sum
+= case_data (c
, s
->items
[v
])->f
;
439 case_processing_summary (casenumber n_valid
, casenumber n_missing
,
440 const struct dictionary
*dict
);
444 alpha (int k
, double sum_of_variances
, double variance_of_sums
)
446 return k
/ ( k
- 1.0) * ( 1 - sum_of_variances
/ variance_of_sums
);
450 do_reliability (struct casereader
*input
, struct dataset
*ds
,
451 const struct reliability
*rel
)
456 casenumber n_missing
;
457 casenumber n_valid
= 0;
460 for (si
= 0 ; si
< rel
->n_sc
; ++si
)
462 struct cronbach
*s
= &rel
->sc
[si
];
464 moments1_clear (s
->total
);
466 for (i
= 0 ; i
< s
->n_items
; ++i
)
467 moments1_clear (s
->m
[i
]);
470 input
= casereader_create_filter_missing (input
,
477 for (si
= 0 ; si
< rel
->n_sc
; ++si
)
479 struct cronbach
*s
= &rel
->sc
[si
];
482 s
->totals_idx
= caseproto_get_n_widths (casereader_get_proto (input
));
484 casereader_create_append_numeric (input
, append_sum
,
488 for (; (c
= casereader_read (input
)) != NULL
; case_unref (c
))
493 for (si
= 0; si
< rel
->n_sc
; ++si
)
495 struct cronbach
*s
= &rel
->sc
[si
];
497 for (i
= 0 ; i
< s
->n_items
; ++i
)
498 moments1_add (s
->m
[i
], case_data (c
, s
->items
[i
])->f
, weight
);
500 moments1_add (s
->total
, case_data_idx (c
, s
->totals_idx
)->f
, weight
);
503 casereader_destroy (input
);
505 for (si
= 0; si
< rel
->n_sc
; ++si
)
507 struct cronbach
*s
= &rel
->sc
[si
];
509 s
->sum_of_variances
= 0;
510 for (i
= 0 ; i
< s
->n_items
; ++i
)
512 double weight
, mean
, variance
;
513 moments1_calculate (s
->m
[i
], &weight
, &mean
, &variance
, NULL
, NULL
);
515 s
->sum_of_variances
+= variance
;
518 moments1_calculate (s
->total
, NULL
, NULL
, &s
->variance_of_sums
,
522 alpha (s
->n_items
, s
->sum_of_variances
, s
->variance_of_sums
);
525 text_item_submit (text_item_create_format (TEXT_ITEM_PARAGRAPH
, _("Scale: %s"),
526 ds_cstr (&rel
->scale_name
)));
528 case_processing_summary (n_valid
, n_missing
, dataset_dict (ds
));
536 case_processing_summary (casenumber n_valid
, casenumber n_missing
,
537 const struct dictionary
*dict
)
539 const struct variable
*wv
= dict_get_weight (dict
);
540 const struct fmt_spec
*wfmt
= wv
? var_get_print_format (wv
) : & F_8_0
;
545 int heading_columns
= 2;
546 int heading_rows
= 1;
547 struct tab_table
*tbl
;
548 tbl
= tab_create (n_cols
, n_rows
);
549 tab_set_format (tbl
, RC_WEIGHT
, wfmt
);
550 tab_headers (tbl
, heading_columns
, 0, heading_rows
, 0);
552 tab_title (tbl
, _("Case Processing Summary"));
554 /* Vertical lines for the data only */
559 n_cols
- 1, n_rows
- 1);
561 /* Box around table */
566 n_cols
- 1, n_rows
- 1);
569 tab_hline (tbl
, TAL_2
, 0, n_cols
- 1, heading_rows
);
571 tab_vline (tbl
, TAL_2
, heading_columns
, 0, n_rows
- 1);
574 tab_text (tbl
, 0, heading_rows
, TAB_LEFT
| TAT_TITLE
,
577 tab_text (tbl
, 1, heading_rows
, TAB_LEFT
| TAT_TITLE
,
580 tab_text (tbl
, 1, heading_rows
+ 1, TAB_LEFT
| TAT_TITLE
,
583 tab_text (tbl
, 1, heading_rows
+ 2, TAB_LEFT
| TAT_TITLE
,
586 tab_text (tbl
, heading_columns
, 0, TAB_CENTER
| TAT_TITLE
,
589 tab_text (tbl
, heading_columns
+ 1, 0, TAB_CENTER
| TAT_TITLE
, _("%"));
591 total
= n_missing
+ n_valid
;
593 tab_double (tbl
, 2, heading_rows
, TAB_RIGHT
,
594 n_valid
, NULL
, RC_WEIGHT
);
597 tab_double (tbl
, 2, heading_rows
+ 1, TAB_RIGHT
,
598 n_missing
, NULL
, RC_WEIGHT
);
601 tab_double (tbl
, 2, heading_rows
+ 2, TAB_RIGHT
,
602 total
, NULL
, RC_WEIGHT
);
605 tab_double (tbl
, 3, heading_rows
, TAB_RIGHT
,
606 100 * n_valid
/ (double) total
, NULL
, RC_OTHER
);
609 tab_double (tbl
, 3, heading_rows
+ 1, TAB_RIGHT
,
610 100 * n_missing
/ (double) total
, NULL
, RC_OTHER
);
613 tab_double (tbl
, 3, heading_rows
+ 2, TAB_RIGHT
,
614 100 * total
/ (double) total
, NULL
, RC_OTHER
);
623 reliability_summary_total (const struct reliability
*rel
)
626 const int n_cols
= 5;
627 const int heading_columns
= 1;
628 const int heading_rows
= 1;
629 const int n_rows
= rel
->sc
[0].n_items
+ heading_rows
;
630 const struct variable
*wv
= rel
->wv
;
631 const struct fmt_spec
*wfmt
= wv
? var_get_print_format (wv
) : & F_8_0
;
632 struct tab_table
*tbl
= tab_create (n_cols
, n_rows
);
633 tab_set_format (tbl
, RC_WEIGHT
, wfmt
);
634 tab_headers (tbl
, heading_columns
, 0, heading_rows
, 0);
636 tab_title (tbl
, _("Item-Total Statistics"));
638 /* Vertical lines for the data only */
643 n_cols
- 1, n_rows
- 1);
645 /* Box around table */
650 n_cols
- 1, n_rows
- 1);
653 tab_hline (tbl
, TAL_2
, 0, n_cols
- 1, heading_rows
);
655 tab_vline (tbl
, TAL_2
, heading_columns
, 0, n_rows
- 1);
657 tab_text (tbl
, 1, 0, TAB_CENTER
| TAT_TITLE
,
658 _("Scale Mean if Item Deleted"));
660 tab_text (tbl
, 2, 0, TAB_CENTER
| TAT_TITLE
,
661 _("Scale Variance if Item Deleted"));
663 tab_text (tbl
, 3, 0, TAB_CENTER
| TAT_TITLE
,
664 _("Corrected Item-Total Correlation"));
666 tab_text (tbl
, 4, 0, TAB_CENTER
| TAT_TITLE
,
667 _("Cronbach's Alpha if Item Deleted"));
670 for (i
= 0 ; i
< rel
->sc
[0].n_items
; ++i
)
672 double cov
, item_to_total_r
;
673 double mean
, weight
, var
;
675 const struct cronbach
*s
= &rel
->sc
[rel
->total_start
+ i
];
676 tab_text (tbl
, 0, heading_rows
+ i
, TAB_LEFT
| TAT_TITLE
,
677 var_to_string (rel
->sc
[0].items
[i
]));
679 moments1_calculate (s
->total
, &weight
, &mean
, &var
, 0, 0);
681 tab_double (tbl
, 1, heading_rows
+ i
, TAB_RIGHT
,
682 mean
, NULL
, RC_OTHER
);
684 tab_double (tbl
, 2, heading_rows
+ i
, TAB_RIGHT
,
685 s
->variance_of_sums
, NULL
, RC_OTHER
);
687 tab_double (tbl
, 4, heading_rows
+ i
, TAB_RIGHT
,
688 s
->alpha
, NULL
, RC_OTHER
);
691 moments1_calculate (rel
->sc
[0].m
[i
], &weight
, &mean
, &var
, 0,0);
692 cov
= rel
->sc
[0].variance_of_sums
+ var
- s
->variance_of_sums
;
695 item_to_total_r
= (cov
- var
) / (sqrt(var
) * sqrt (s
->variance_of_sums
));
698 tab_double (tbl
, 3, heading_rows
+ i
, TAB_RIGHT
,
699 item_to_total_r
, NULL
, RC_OTHER
);
707 static void reliability_statistics_model_alpha (struct tab_table
*tbl
,
708 const struct reliability
*rel
);
710 static void reliability_statistics_model_split (struct tab_table
*tbl
,
711 const struct reliability
*rel
);
714 struct reliability_output_table
720 void (*populate
) (struct tab_table
*, const struct reliability
*);
724 static struct reliability_output_table rol
[2] =
726 { 2, 2, 1, 1, reliability_statistics_model_alpha
},
727 { 4, 9, 3, 0, reliability_statistics_model_split
}
731 reliability_statistics (const struct reliability
*rel
)
733 int n_cols
= rol
[rel
->model
].n_cols
;
734 int n_rows
= rol
[rel
->model
].n_rows
;
735 int heading_columns
= rol
[rel
->model
].heading_cols
;
736 int heading_rows
= rol
[rel
->model
].heading_rows
;
737 const struct variable
*wv
= rel
->wv
;
738 const struct fmt_spec
*wfmt
= wv
? var_get_print_format (wv
) : & F_8_0
;
739 struct tab_table
*tbl
= tab_create (n_cols
, n_rows
);
740 tab_set_format (tbl
, RC_WEIGHT
, wfmt
);
742 tab_headers (tbl
, heading_columns
, 0, heading_rows
, 0);
744 tab_title (tbl
, _("Reliability Statistics"));
746 /* Vertical lines for the data only */
751 n_cols
- 1, n_rows
- 1);
753 /* Box around table */
758 n_cols
- 1, n_rows
- 1);
761 tab_hline (tbl
, TAL_2
, 0, n_cols
- 1, heading_rows
);
763 tab_vline (tbl
, TAL_2
, heading_columns
, 0, n_rows
- 1);
765 if ( rel
->model
== MODEL_ALPHA
)
766 reliability_statistics_model_alpha (tbl
, rel
);
767 else if (rel
->model
== MODEL_SPLIT
)
768 reliability_statistics_model_split (tbl
, rel
);
775 reliability_statistics_model_alpha (struct tab_table
*tbl
,
776 const struct reliability
*rel
)
778 const struct cronbach
*s
= &rel
->sc
[0];
780 tab_text (tbl
, 0, 0, TAB_CENTER
| TAT_TITLE
,
781 _("Cronbach's Alpha"));
783 tab_text (tbl
, 1, 0, TAB_CENTER
| TAT_TITLE
,
786 tab_double (tbl
, 0, 1, TAB_RIGHT
, s
->alpha
, NULL
, RC_OTHER
);
788 tab_double (tbl
, 1, 1, TAB_RIGHT
, s
->n_items
, NULL
, RC_WEIGHT
);
793 reliability_statistics_model_split (struct tab_table
*tbl
,
794 const struct reliability
*rel
)
796 tab_text (tbl
, 0, 0, TAB_LEFT
,
797 _("Cronbach's Alpha"));
799 tab_text (tbl
, 1, 0, TAB_LEFT
,
802 tab_text (tbl
, 2, 0, TAB_LEFT
,
805 tab_text (tbl
, 2, 1, TAB_LEFT
,
808 tab_text (tbl
, 1, 2, TAB_LEFT
,
811 tab_text (tbl
, 2, 2, TAB_LEFT
,
814 tab_text (tbl
, 2, 3, TAB_LEFT
,
817 tab_text (tbl
, 1, 4, TAB_LEFT
,
818 _("Total N of Items"));
820 tab_text (tbl
, 0, 5, TAB_LEFT
,
821 _("Correlation Between Forms"));
823 tab_text (tbl
, 0, 6, TAB_LEFT
,
824 _("Spearman-Brown Coefficient"));
826 tab_text (tbl
, 1, 6, TAB_LEFT
,
829 tab_text (tbl
, 1, 7, TAB_LEFT
,
830 _("Unequal Length"));
833 tab_text (tbl
, 0, 8, TAB_LEFT
,
834 _("Guttman Split-Half Coefficient"));
838 tab_double (tbl
, 3, 0, TAB_RIGHT
, rel
->sc
[1].alpha
, NULL
, RC_OTHER
);
839 tab_double (tbl
, 3, 2, TAB_RIGHT
, rel
->sc
[2].alpha
, NULL
, RC_OTHER
);
841 tab_double (tbl
, 3, 1, TAB_RIGHT
, rel
->sc
[1].n_items
, NULL
, RC_WEIGHT
);
842 tab_double (tbl
, 3, 3, TAB_RIGHT
, rel
->sc
[2].n_items
, NULL
, RC_WEIGHT
);
844 tab_double (tbl
, 3, 4, TAB_RIGHT
,
845 rel
->sc
[1].n_items
+ rel
->sc
[2].n_items
, NULL
, RC_WEIGHT
);
848 /* R is the correlation between the two parts */
849 double r
= rel
->sc
[0].variance_of_sums
-
850 rel
->sc
[1].variance_of_sums
-
851 rel
->sc
[2].variance_of_sums
;
853 /* Guttman Split Half Coefficient */
854 double g
= 2 * r
/ rel
->sc
[0].variance_of_sums
;
856 /* Unequal Length Spearman Brown Coefficient, and
857 intermediate value used in the computation thereof */
860 r
/= sqrt (rel
->sc
[1].variance_of_sums
);
861 r
/= sqrt (rel
->sc
[2].variance_of_sums
);
864 tab_double (tbl
, 3, 5, TAB_RIGHT
, r
, NULL
, RC_OTHER
);
866 /* Equal length Spearman-Brown Coefficient */
867 tab_double (tbl
, 3, 6, TAB_RIGHT
, 2 * r
/ (1.0 + r
), NULL
, RC_OTHER
);
869 tab_double (tbl
, 3, 8, TAB_RIGHT
, g
, NULL
, RC_OTHER
);
871 tmp
= (1.0 - r
*r
) * rel
->sc
[1].n_items
* rel
->sc
[2].n_items
/
872 pow2 (rel
->sc
[0].n_items
);
874 uly
= sqrt( pow4 (r
) + 4 * pow2 (r
) * tmp
);
878 tab_double (tbl
, 3, 7, TAB_RIGHT
, uly
, NULL
, RC_OTHER
);