15d21ecee124cd13fa817e6fb90af2a3ce8d8306
[pspp-builds.git] / src / language / stats / correlations.q
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21
22 #include <stdlib.h>
23
24 #include <data/dictionary.h>
25 #include <data/file-handle-def.h>
26 #include <data/procedure.h>
27 #include <data/variable.h>
28 #include <language/command.h>
29 #include <language/data-io/file-handle.h>
30 #include <language/lexer/lexer.h>
31 #include <language/lexer/variable-parser.h>
32 #include <libpspp/alloc.h>
33 #include <libpspp/compiler.h>
34
35 /* (headers) */
36
37 struct cor_set
38   {
39     struct cor_set *next;
40     struct variable **v1, **v2;
41     size_t nv1, nv2;
42   };
43
44 static struct cor_set *cor_list, *cor_last;
45
46 static struct file_handle *matrix_file;
47
48 static void free_correlations_state (void);
49 static int internal_cmd_correlations (struct lexer *lexer, struct dataset *ds);
50
51 int
52 cmd_correlations (struct lexer *lexer, struct dataset *ds)
53 {
54   int result = internal_cmd_correlations (lexer, ds);
55   free_correlations_state ();
56   return result;
57 }
58
59 /* (specification)
60    "CORRELATIONS" (cor_):
61      *variables=custom;
62      missing=miss:!pairwise/listwise,
63              inc:include/exclude;
64      +print=tail:!twotail/onetail,
65             sig:!sig/nosig;
66      +format=fmt:!matrix/serial;
67      +matrix=custom;
68      +statistics[st_]=descriptives,xprod,all.
69 */
70 /* (declarations) */
71 /* (functions) */
72
73 int
74 internal_cmd_correlations (struct lexer *lexer, struct dataset *ds)
75 {
76   struct cmd_correlations cmd;
77
78   cor_list = cor_last = NULL;
79   matrix_file = NULL;
80
81   if (!parse_correlations (lexer, ds, &cmd, NULL))
82     return CMD_FAILURE;
83
84   free_correlations (&cmd);
85
86   return CMD_SUCCESS;
87 }
88
89 static int
90 cor_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_correlations *cmd UNUSED, void *aux UNUSED)
91 {
92   struct variable **v1, **v2;
93   size_t nv1, nv2;
94   struct cor_set *cor;
95
96   /* Ensure that this is a VARIABLES subcommand. */
97   if (!lex_match_id (lexer, "VARIABLES")
98       && (lex_token (lexer) != T_ID || dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL)
99       && lex_token (lexer) != T_ALL)
100     return 2;
101   lex_match (lexer, '=');
102
103   if (!parse_variables (lexer, dataset_dict (ds), &v1, &nv1,
104                         PV_NO_DUPLICATE | PV_NUMERIC))
105     return 0;
106   
107   if (lex_match (lexer, T_WITH))
108     {
109       if (!parse_variables (lexer, dataset_dict (ds), &v2, &nv2,
110                             PV_NO_DUPLICATE | PV_NUMERIC))
111         {
112           free (v1);
113           return 0;
114         }
115     }
116   else
117     {
118       nv2 = nv1;
119       v2 = v1;
120     }
121
122   cor = xmalloc (sizeof *cor);
123   cor->next = NULL;
124   cor->v1 = v1;
125   cor->v2 = v2;
126   cor->nv1 = nv1;
127   cor->nv2 = nv2;
128   if (cor_list)
129     cor_last = cor_last->next = cor;
130   else
131     cor_list = cor_last = cor;
132   
133   return 1;
134 }
135
136 static int
137 cor_custom_matrix (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_correlations *cmd UNUSED, void *aux UNUSED)
138 {
139   if (!lex_force_match (lexer, '('))
140     return 0;
141   
142   if (lex_match (lexer, '*'))
143     matrix_file = NULL;
144   else 
145     {
146       matrix_file = fh_parse (lexer, FH_REF_FILE);
147       if (matrix_file == NULL)
148         return 0; 
149     }
150
151   if (!lex_force_match (lexer, ')'))
152     return 0;
153
154   return 1;
155 }
156
157 static void
158 free_correlations_state (void)
159 {
160   struct cor_set *cor, *next;
161
162   for (cor = cor_list; cor != NULL; cor = next)
163     {
164       next = cor->next;
165       if (cor->v1 != cor->v2)
166         free (cor->v2);
167       free (cor->v1);
168       free (cor);
169     }
170 }
171
172 /*
173   Local Variables:
174   mode: c
175   End:
176 */