some more mconvert
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 27 Sep 2021 02:26:14 +0000 (19:26 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 27 Sep 2021 02:26:14 +0000 (19:26 -0700)
src/language/data-io/matrix-reader.c
src/language/data-io/matrix-reader.h
src/language/data-io/mconvert.c

index a1ef1e2331efaf2db6525e58083c217c42a73fa2..c2d06a071dac88cf276657b63591c1321ed2cb17 100644 (file)
@@ -119,6 +119,15 @@ matrix_reader_create (const struct dictionary *dict,
   if (!varname || !rowtype)
     return NULL;
 
+  size_t varname_idx = var_get_dict_index (varname);
+  size_t rowtype_idx = var_get_dict_index (rowtype);
+  if (varname_idx < rowtype_idx)
+    {
+      msg (ME, _("Variable %s must precede %s in matrix file dictionary."),
+           "ROWTYPE_", "VARNAME_");
+      return NULL;
+    }
+
   for (size_t i = 0; i < dict_get_var_cnt (dict); i++)
     {
       const struct variable *v = dict_get_var (dict, i);
@@ -130,32 +139,38 @@ matrix_reader_create (const struct dictionary *dict,
         }
     }
 
-  size_t dvarcnt;
-  const struct variable **dvars = NULL;
-  dict_get_vars (dict, &dvars, &dvarcnt, DC_SCRATCH);
-
-  /* Continuous variables and split variables. */
-  const struct variable **cvars = dvars + var_get_dict_index (varname) + 1;
-  size_t n_cvars = dvarcnt - var_get_dict_index (varname) - 1;
-  const struct variable **svars = dvars;
-  size_t n_svars = var_get_dict_index (rowtype);
+  size_t n_vars;
+  const struct variable **vars;
+  dict_get_vars (dict, &vars, &n_vars, DC_SCRATCH);
+
+  /* Different kinds of variables. */
+  size_t first_svar = 0;
+  size_t n_svars = rowtype_idx;
+  size_t first_fvar = rowtype_idx + 1;
+  size_t n_fvars = varname_idx - rowtype_idx - 1;
+  size_t first_cvar = varname_idx + 1;
+  size_t n_cvars = n_vars - varname_idx - 1;
   if (!n_cvars)
     {
       msg (ME, _("Matrix dataset does not have any continuous variables."));
-      free (dvars);
+      free (vars);
       return NULL;
     }
 
   struct matrix_reader *mr = xmalloc (sizeof *mr);
   *mr = (struct matrix_reader) {
-    .n_cvars = n_cvars,
-    .cvars = xmemdup (cvars, n_cvars * sizeof *cvars),
+    .dict = dict,
+    .grouper = casegrouper_create_vars (in_reader, &vars[first_svar], n_svars),
+    .svars = xmemdup (vars + first_svar, n_svars * sizeof *mr->svars),
+    .n_svars = n_svars,
     .rowtype = rowtype,
+    .fvars = xmemdup (vars + first_fvar, n_fvars * sizeof *mr->fvars),
+    .n_fvars = n_fvars,
     .varname = varname,
-    .dict = dict,
-    .grouper = casegrouper_create_vars (in_reader, svars, n_svars)
+    .cvars = xmemdup (vars + first_cvar, n_cvars * sizeof *mr->cvars),
+    .n_cvars = n_cvars,
   };
-  free (dvars);
+  free (vars);
 
   return mr;
 }
index a0e0bb8ea23d0ff4247bf933961819405c8be1a9..5aec05e009f4a0f19bdb776b40aeef3b0168c764 100644 (file)
@@ -32,10 +32,14 @@ struct matrix_reader
     struct casegrouper *grouper;
 
     /* Variables in 'dict'. */
-    const struct variable **cvars;  /* Continuous variables. */
-    size_t n_cvars;
+    const struct variable **svars;  /* Split variables. */
+    size_t n_svars;
     const struct variable *rowtype; /* ROWTYPE_. */
+    const struct variable **fvars;  /* Factor variables. */
+    size_t n_fvars;
     const struct variable *varname; /* VARNAME_. */
+    const struct variable **cvars;  /* Continuous variables. */
+    size_t n_cvars;
   };
 
 struct matrix_material
index 78a0d212d9d9a253f1e0550b3f107d68270bcace..1e24464709e09195b88b8dcb15f7445b471df60b 100644 (file)
@@ -35,7 +35,7 @@
 int
 cmd_mconvert (struct lexer *lexer, struct dataset *ds)
 {
-  bool append UNUSED = false;
+  bool append = false;
   struct file_handle *in = NULL;
   struct file_handle *out = NULL;
   while (lex_token (lexer) != T_ENDCMD)
@@ -116,28 +116,31 @@ cmd_mconvert (struct lexer *lexer, struct dataset *ds)
       if (!matrix_reader_next (&mm, mr, &group))
         break;
 
-      struct ccase *model = NULL;
+      bool add_corr = mm.cov && !mm.corr;
+      bool add_cov = mm.corr && !mm.cov;
+      bool remove_corr = add_cov && !append;
+      bool remove_cov = add_corr && !append;
+
+      struct ccase *model = casereader_peek (group, 0);
+      for (size_t i = 0; i < mr->n_fvars; i++)
+        *case_num_rw (model, mr->fvars[i]) = SYSMIS;
+
       for (;;)
         {
           struct ccase *c = casereader_read (group);
           if (!c)
             break;
 
-          if (!model)
-            {
-              struct substring rowtype
-                = matrix_reader_get_string (c, mr->rowtype);
-              if (ss_equals_case (rowtype, ss_cstr ("COV"))
-                  || ss_equals_case (rowtype, ss_cstr ("CORR")))
-                model = case_ref (c);
-            }
-          casewriter_write (cw, c);
+          struct substring rowtype = matrix_reader_get_string (c, mr->rowtype);
+          if ((remove_cov && ss_equals_case (rowtype, ss_cstr ("COV")))
+              || (remove_corr && ss_equals_case (rowtype, ss_cstr ("CORR"))))
+            case_unref (c);
+          else
+            casewriter_write (cw, c);
         }
+      casereader_destroy (group);
 
-      if (!model)
-        continue;
-
-      if (mm.cov && !mm.corr)
+      if (add_corr)
         {
           assert (mm.cov->size1 == mr->n_cvars);
           assert (mm.cov->size2 == mr->n_cvars);
@@ -169,7 +172,7 @@ cmd_mconvert (struct lexer *lexer, struct dataset *ds)
           casewriter_write (cw, c);
         }
 
-      if (mm.corr && !mm.cov)
+      if (add_cov)
         {
           assert (mm.corr->size1 == mr->n_cvars);
           assert (mm.corr->size2 == mr->n_cvars);
@@ -184,6 +187,9 @@ cmd_mconvert (struct lexer *lexer, struct dataset *ds)
                   double corr = gsl_matrix_get (mm.corr, y, x);
                   *case_num_rw (c, mr->cvars[x]) = corr * sqrt (d1 * d2);
                 }
+              matrix_reader_set_string (c, mr->rowtype, ss_cstr ("COV"));
+              matrix_reader_set_string (c, mr->varname,
+                                        ss_cstr (var_get_name (mr->cvars[y])));
               casewriter_write (cw, c);
             }
         }