Enable R_NO_REMAP for a cleaner namespace
[openmx:openmx.git] / src / omxFIMLFitFunction.cpp
1 /*
2  *  Copyright 2007-2014 The OpenMx Project
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 #include "omxDefines.h"
18 #include "omxAlgebraFunctions.h"
19 #include "omxSymbolTable.h"
20 #include "omxData.h"
21 #include "omxFIMLFitFunction.h"
22 #include "omxFIMLSingleIteration.h"
23 #include "omxSadmvnWrapper.h"
24
25 #define max(a,b) \
26    ({ __typeof__ (a) _a = (a); \
27        __typeof__ (b) _b = (b); \
28      _a > _b ? _a : _b; })
29
30 /* FIML Function body */
31 void omxDestroyFIMLFitFunction(omxFitFunction *off) {
32         if(OMX_DEBUG) { mxLog("Destroying FIML fit function object."); }
33         omxFIMLFitFunction *argStruct = (omxFIMLFitFunction*) (off->argStruct);
34
35         if(argStruct->smallMeans != NULL) omxFreeMatrixData(argStruct->smallMeans);
36         if(argStruct->ordMeans != NULL) omxFreeMatrixData(argStruct->ordMeans);
37         if(argStruct->contRow != NULL) omxFreeMatrixData(argStruct->contRow);
38         if(argStruct->ordRow != NULL) omxFreeMatrixData(argStruct->ordRow);
39         if(argStruct->ordCov != NULL) omxFreeMatrixData(argStruct->ordCov);
40         if(argStruct->ordContCov != NULL) omxFreeMatrixData(argStruct->ordContCov);
41         if(argStruct->halfCov != NULL) omxFreeMatrixData(argStruct->halfCov);
42         if(argStruct->reduceCov != NULL) omxFreeMatrixData(argStruct->reduceCov);
43
44         if(argStruct->smallRow != NULL) omxFreeMatrixData(argStruct->smallRow);
45         if(argStruct->smallCov != NULL) omxFreeMatrixData(argStruct->smallCov);
46         if(argStruct->RCX != NULL)              omxFreeMatrixData(argStruct->RCX);
47     if(argStruct->rowLikelihoods != NULL) omxFreeMatrixData(argStruct->rowLikelihoods);
48     if(argStruct->rowLogLikelihoods != NULL) omxFreeMatrixData(argStruct->rowLogLikelihoods);
49         if(off->expectation == NULL) {
50                 if(argStruct->cov != NULL) omxFreeMatrixData(argStruct->cov);
51                 if(argStruct->means != NULL) omxFreeMatrixData(argStruct->means);
52         }
53 }
54
55 void omxPopulateFIMLAttributes(omxFitFunction *off, SEXP algebra) {
56         omxFIMLFitFunction *argStruct = ((omxFIMLFitFunction*)off->argStruct);
57         SEXP expCovExt, expMeanExt, rowLikelihoodsExt;
58         omxMatrix *expCovInt, *expMeanInt, *rowLikelihoodsInt;
59         expCovInt = argStruct->cov;
60         expMeanInt = argStruct->means;
61         rowLikelihoodsInt = argStruct->rowLikelihoods;
62
63         Rf_protect(expCovExt = Rf_allocMatrix(REALSXP, expCovInt->rows, expCovInt->cols));
64         for(int row = 0; row < expCovInt->rows; row++)
65                 for(int col = 0; col < expCovInt->cols; col++)
66                         REAL(expCovExt)[col * expCovInt->rows + row] =
67                                 omxMatrixElement(expCovInt, row, col);
68         if (expMeanInt != NULL) {
69                 Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, expMeanInt->rows, expMeanInt->cols));
70                 for(int row = 0; row < expMeanInt->rows; row++)
71                         for(int col = 0; col < expMeanInt->cols; col++)
72                                 REAL(expMeanExt)[col * expMeanInt->rows + row] =
73                                         omxMatrixElement(expMeanInt, row, col);
74         } else {
75                 Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, 0, 0));         
76         }
77         Rf_protect(rowLikelihoodsExt = Rf_allocVector(REALSXP, rowLikelihoodsInt->rows));
78         for(int row = 0; row < rowLikelihoodsInt->rows; row++)
79                 REAL(rowLikelihoodsExt)[row] = omxMatrixElement(rowLikelihoodsInt, row, 0);
80
81         Rf_setAttrib(algebra, Rf_install("expCov"), expCovExt);
82         Rf_setAttrib(algebra, Rf_install("expMean"), expMeanExt);
83         Rf_setAttrib(algebra, Rf_install("likelihoods"), rowLikelihoodsExt);
84
85         Rf_unprotect(3); // expCovExp, expCovInt, rowLikelihoodsExt
86 }
87
88 omxRListElement* omxSetFinalReturnsFIMLFitFunction(omxFitFunction *off, int *numReturns)
89 {
90         // DEPRECATED use omxPopulateFIMLAttributes
91         omxFIMLFitFunction* ofiml = (omxFIMLFitFunction *) (off->argStruct);
92
93         if(!ofiml->returnRowLikelihoods) return NULL;
94
95         omxRListElement *retVal = (omxRListElement*) R_alloc(1, sizeof(omxRListElement));
96         omxData* data = ofiml->data;
97         retVal[0].numValues = data->rows;
98         retVal[0].values = (double*) R_alloc(data->rows, sizeof(double));
99
100         return retVal;
101 }
102
103 void markDefVarDependencies(omxState* os, omxDefinitionVar* defVar) {
104
105         int numDeps = defVar->numDeps;
106         int *deps = defVar->deps;
107
108         for (int i = 0; i < numDeps; i++) {
109                 int value = deps[i];
110
111                 if(value < 0) {
112                         omxMarkDirty(os->matrixList[~value]);
113                 } else {
114                         omxMarkDirty(os->algebraList[value]);
115                 }
116         }
117
118 }
119
120 int handleDefinitionVarList(omxData* data, omxState *state, int row, omxDefinitionVar* defVars, double* oldDefs, int numDefs) {
121
122         if(OMX_DEBUG_ROWS(row)) { mxLog("Processing Definition Vars."); }
123         
124         int numVarsFilled = 0;
125
126         /* Fill in Definition Var Estimates */
127         for(int k = 0; k < numDefs; k++) {
128                 if(defVars[k].source != data) {
129                         Rf_error("Internal Rf_error: definition variable population into incorrect data source");
130                 }
131                 double newDefVar = omxDoubleDataElement(data, row, defVars[k].column);
132                 if(ISNA(newDefVar)) {
133                         Rf_error("Error: NA value for a definition variable is Not Yet Implemented.");
134                 }
135                 if(newDefVar == oldDefs[k]) {
136                         continue;       // NOTE: Potential speedup vs accuracy tradeoff here using epsilon comparison
137                 }
138                 oldDefs[k] = newDefVar;
139                 numVarsFilled++;
140
141                 for(int l = 0; l < defVars[k].numLocations; l++) {
142                         if(OMX_DEBUG_ROWS(row)) {
143                                 mxLog("Populating column %d (value %3.2f) into matrix %d.", defVars[k].column, omxDoubleDataElement(defVars[k].source, row, defVars[k].column), defVars[k].matrices[l]);
144                         }
145                         int matrixNumber = defVars[k].matrices[l];
146                         int matrow = defVars[k].rows[l];
147                         int matcol = defVars[k].cols[l];
148                         omxMatrix *matrix = state->matrixList[matrixNumber];
149                         omxSetMatrixElement(matrix, matrow, matcol, newDefVar);
150                 }
151                 markDefVarDependencies(state, &(defVars[k]));
152         }
153         return numVarsFilled;
154 }
155
156 static void omxCallJointFIMLFitFunction(omxFitFunction *off, int want, FitContext *) {
157         // TODO: Figure out how to give access to other per-iteration structures.
158         // TODO: Current implementation is slow: update by filtering correlations and thresholds.
159         // TODO: Current implementation does not implement speedups for sorting.
160         // TODO: Current implementation may fail on all-continuous-missing or all-ordinal-missing rows.
161         
162         if (want & (FF_COMPUTE_PREOPTIMIZE)) return;
163
164     if(OMX_DEBUG) { 
165             mxLog("Beginning Joint FIML Evaluation.");
166     }
167         // Requires: Data, means, covariances, thresholds
168
169         int numDefs;
170
171         int returnRowLikelihoods = 0;
172
173         omxMatrix *cov, *means, *dataColumns;
174
175         omxThresholdColumn *thresholdCols;
176         omxData* data;
177         
178         omxExpectation* expectation;
179
180         omxFIMLFitFunction* ofiml = ((omxFIMLFitFunction*)off->argStruct);
181         omxMatrix* fitMatrix  = off->matrix;
182         omxState* parentState = fitMatrix->currentState;
183         int numChildren = parentState==globalState? Global->numChildren : 0;
184
185         cov             = ofiml->cov;
186         means           = ofiml->means;
187         data            = ofiml->data;                            //  read-only
188         numDefs         = ofiml->numDefs;                         //  read-only
189         dataColumns     = ofiml->dataColumns;
190         thresholdCols = ofiml->thresholdCols;
191
192         returnRowLikelihoods = ofiml->returnRowLikelihoods;   //  read-only
193         expectation = off->expectation;
194
195
196     if(numDefs == 0) {
197         if(OMX_DEBUG) {mxLog("Precalculating cov and means for all rows.");}
198                 omxExpectationRecompute(expectation);
199                 // MCN Also do the threshold formulae!
200                 
201                 for(int j=0; j < dataColumns->cols; j++) {
202                         int var = omxVectorElement(dataColumns, j);
203                         if(omxDataColumnIsFactor(data, j) && thresholdCols[var].numThresholds > 0) { // j is an ordinal column
204                                 omxMatrix* nextMatrix = thresholdCols[var].matrix;
205                                 omxRecompute(nextMatrix);
206                                 checkIncreasing(nextMatrix, thresholdCols[var].column);
207                                 for(int index = 0; index < numChildren; index++) {
208                                         omxMatrix *target = omxLookupDuplicateElement(parentState->childList[index], nextMatrix);
209                                         omxCopyMatrix(target, nextMatrix);
210                                 }
211             }
212         }
213                 for(int index = 0; index < numChildren; index++) {
214                         omxMatrix *childFit = omxLookupDuplicateElement(parentState->childList[index], fitMatrix);
215                         omxFIMLFitFunction* childOfiml = ((omxFIMLFitFunction*) childFit->fitFunction->argStruct);
216                         omxCopyMatrix(childOfiml->cov, cov);
217                         omxCopyMatrix(childOfiml->means, means);
218                 }
219         if(OMX_DEBUG) { omxPrintMatrix(cov, "Cov"); }
220         if(OMX_DEBUG) { omxPrintMatrix(means, "Means"); }
221     }
222
223         memset(ofiml->rowLogLikelihoods->data, 0, sizeof(double) * data->rows);
224     
225         int parallelism = (numChildren == 0) ? 1 : numChildren;
226
227         if (parallelism > data->rows) {
228                 parallelism = data->rows;
229         }
230
231         if (parallelism > 1) {
232                 int stride = (data->rows / parallelism);
233
234                 #pragma omp parallel for num_threads(parallelism) 
235                 for(int i = 0; i < parallelism; i++) {
236                         omxMatrix *childMatrix = omxLookupDuplicateElement(parentState->childList[i], fitMatrix);
237                         omxFitFunction *childFit = childMatrix->fitFunction;
238                         if (i == parallelism - 1) {
239                                 omxFIMLSingleIterationJoint(childFit, off, stride * i, data->rows - stride * i);
240                         } else {
241                                 omxFIMLSingleIterationJoint(childFit, off, stride * i, stride);
242                         }
243                 }
244
245                 for(int i = 0; i < parallelism; i++) {
246                         if (isErrorRaised(parentState->childList[i])) {
247                                 strncpy(parentState->statusMsg, parentState->childList[i]->statusMsg, MAX_STRING_LEN);
248                         }
249                 }
250
251         } else {
252                 omxFIMLSingleIterationJoint(off, off, 0, data->rows);
253         }
254
255         if(!returnRowLikelihoods) {
256                 double val, sum = 0.0;
257                 // floating-point addition is not associative,
258                 // so we serialized the following reduction operation.
259                 for(int i = 0; i < data->rows; i++) {
260                         val = omxVectorElement(ofiml->rowLogLikelihoods, i);
261 //                      mxLog("%d , %f, %llx\n", i, val, *((unsigned long long*) &val));
262                         sum += val;
263                 }       
264                 if(OMX_VERBOSE || OMX_DEBUG) {mxLog("Total Likelihood is %3.3f", sum);}
265                 omxSetMatrixElement(off->matrix, 0, 0, sum);
266         }
267
268 }
269
270 static void omxCallFIMLFitFunction(omxFitFunction *off, int want, FitContext *) {
271
272         if (want & (FF_COMPUTE_PREOPTIMIZE)) return;
273
274         if(OMX_DEBUG) { mxLog("Beginning FIML Evaluation."); }
275         // Requires: Data, means, covariances.
276         // Potential Problem: Definition variables currently are assumed to be at the end of the data matrix.
277
278         int numDefs, returnRowLikelihoods;      
279         omxExpectation* expectation;
280         
281         omxMatrix *cov, *means;//, *oldInverse;
282         omxData *data;
283
284         omxFIMLFitFunction* ofiml = ((omxFIMLFitFunction*) off->argStruct);
285         omxMatrix* objMatrix  = off->matrix;
286         omxState* parentState = objMatrix->currentState;
287         int numChildren = parentState==globalState? Global->numChildren : 0;
288
289         // Locals, for readability.  Should compile out.
290         cov             = ofiml->cov;
291         means           = ofiml->means;
292         data            = ofiml->data;                            //  read-only
293         numDefs         = ofiml->numDefs;                         //  read-only
294         returnRowLikelihoods = ofiml->returnRowLikelihoods;   //  read-only
295         expectation = off->expectation;
296
297         if(numDefs == 0 && strcmp(expectation->expType, "MxExpectationStateSpace")) {
298                 if(OMX_DEBUG) {mxLog("Precalculating cov and means for all rows.");}
299                 omxExpectationCompute(expectation, NULL);
300                 
301                 for(int index = 0; index < numChildren; index++) {
302                         omxMatrix *childFit = omxLookupDuplicateElement(parentState->childList[index], objMatrix);
303                         omxFIMLFitFunction* childOfiml = ((omxFIMLFitFunction*) childFit->fitFunction->argStruct);
304                         omxCopyMatrix(childOfiml->cov, cov);
305                         omxCopyMatrix(childOfiml->means, means);
306                 }
307
308                 if(OMX_DEBUG) { omxPrintMatrix(cov, "Cov"); }
309                 if(OMX_DEBUG) { omxPrintMatrix(means, "Means"); }
310         }
311
312         memset(ofiml->rowLogLikelihoods->data, 0, sizeof(double) * data->rows);
313     
314         int parallelism = (numChildren == 0) ? 1 : numChildren;
315
316         if (parallelism > data->rows) {
317                 parallelism = data->rows;
318         }
319
320         if (parallelism > 1) {
321                 int stride = (data->rows / parallelism);
322
323                 #pragma omp parallel for num_threads(parallelism) 
324                 for(int i = 0; i < parallelism; i++) {
325                         omxMatrix *childMatrix = omxLookupDuplicateElement(parentState->childList[i], objMatrix);
326                         omxFitFunction *childFit = childMatrix->fitFunction;
327                         if (i == parallelism - 1) {
328                                 omxFIMLSingleIteration(childFit, off, stride * i, data->rows - stride * i);
329                         } else {
330                                 omxFIMLSingleIteration(childFit, off, stride * i, stride);
331                         }
332                 }
333
334                 for(int i = 0; i < parallelism; i++) {
335                         if (isErrorRaised(parentState->childList[i])) {
336                                 strncpy(parentState->statusMsg, parentState->childList[i]->statusMsg, MAX_STRING_LEN);
337                         }
338                 }
339
340         } else {
341                 omxFIMLSingleIteration(off, off, 0, data->rows);
342         }
343
344         if(!returnRowLikelihoods) {
345                 double val, sum = 0.0;
346                 // floating-point addition is not associative,
347                 // so we serialized the following reduction operation.
348                 for(int i = 0; i < data->rows; i++) {
349                         val = omxVectorElement(ofiml->rowLogLikelihoods, i);
350 //                      mxLog("%d , %f, %llx\n", i, val, *((unsigned long long*) &val));
351                         sum += val;
352                 }       
353                 if(OMX_VERBOSE || OMX_DEBUG) {mxLog("Total Likelihood is %3.3f", sum);}
354                 omxSetMatrixElement(off->matrix, 0, 0, sum);
355         }
356 }
357
358 static void omxCallFIMLOrdinalFitFunction(omxFitFunction *off, int want, FitContext *) {
359         if (want & (FF_COMPUTE_PREOPTIMIZE)) return;
360
361         /* TODO: Current implementation is slow: update by filtering correlations and thresholds. */
362         if(OMX_DEBUG) { mxLog("Beginning Ordinal FIML Evaluation.");}
363         // Requires: Data, means, covariances, thresholds
364
365         int numDefs;
366         int returnRowLikelihoods = 0;
367
368         omxMatrix *cov, *means, *dataColumns;
369         omxThresholdColumn *thresholdCols;
370         omxData* data;
371         double *corList, *weights;
372         
373         omxExpectation* expectation;
374
375         omxFIMLFitFunction* ofiml = ((omxFIMLFitFunction*)off->argStruct);
376         omxMatrix* objMatrix  = off->matrix;
377         omxState* parentState = objMatrix->currentState;
378         int numChildren = parentState==globalState? Global->numChildren : 0;
379
380         // Locals, for readability.  Compiler should cut through this.
381         cov             = ofiml->cov;
382         means           = ofiml->means;
383         data            = ofiml->data;
384         dataColumns     = ofiml->dataColumns;
385         numDefs         = ofiml->numDefs;
386
387         corList         = ofiml->corList;
388         weights         = ofiml->weights;
389         thresholdCols = ofiml->thresholdCols;
390         returnRowLikelihoods = ofiml->returnRowLikelihoods;
391         
392         expectation = off->expectation;
393         
394         if(numDefs == 0) {
395                 if(OMX_DEBUG_ALGEBRA) { mxLog("No Definition Vars: precalculating."); }
396                 omxExpectationCompute(expectation, NULL);
397                 for(int j = 0; j < dataColumns->cols; j++) {
398                         if(thresholdCols[j].numThresholds > 0) { // Actually an ordinal column
399                                 omxMatrix* nextMatrix = thresholdCols[j].matrix;
400                                 omxRecompute(nextMatrix);
401                                 checkIncreasing(nextMatrix, thresholdCols[j].column);
402                                 for(int index = 0; index < numChildren; index++) {
403                                         omxMatrix *target = omxLookupDuplicateElement(parentState->childList[index], nextMatrix);
404                                         omxCopyMatrix(target, nextMatrix);
405                                 }
406                         }
407                 }
408                 omxStandardizeCovMatrix(cov, corList, weights); // Calculate correlation and covariance
409                 for(int index = 0; index < numChildren; index++) {
410                         omxMatrix *childFit = omxLookupDuplicateElement(parentState->childList[index], objMatrix);
411                         omxFIMLFitFunction* childOfiml = ((omxFIMLFitFunction*) childFit->fitFunction->argStruct);
412                         omxCopyMatrix(childOfiml->cov, cov);
413                         omxCopyMatrix(childOfiml->means, means);
414                         memcpy(childOfiml->weights, weights, sizeof(double) * cov->rows);
415                         memcpy(childOfiml->corList, corList, sizeof(double) * (cov->rows * (cov->rows - 1)) / 2);
416                 }
417         }
418
419         memset(ofiml->rowLogLikelihoods->data, 0, sizeof(double) * data->rows);
420
421         int parallelism = (numChildren == 0) ? 1 : numChildren;
422
423         if (parallelism > data->rows) {
424                 parallelism = data->rows;
425         }
426
427         if (parallelism > 1) {
428                 int stride = (data->rows / parallelism);
429
430                 #pragma omp parallel for num_threads(parallelism) 
431                 for(int i = 0; i < parallelism; i++) {
432                         omxMatrix *childMatrix = omxLookupDuplicateElement(parentState->childList[i], objMatrix);
433                         omxFitFunction *childFit = childMatrix->fitFunction;
434                         if (i == parallelism - 1) {
435                                 omxFIMLSingleIterationOrdinal(childFit, off, stride * i, data->rows - stride * i);
436                         } else {
437                                 omxFIMLSingleIterationOrdinal(childFit, off, stride * i, stride);
438                         }
439                 }
440
441                 for(int i = 0; i < parallelism; i++) {
442                         if (isErrorRaised(parentState->childList[i])) {
443                                 strncpy(parentState->statusMsg, parentState->childList[i]->statusMsg, MAX_STRING_LEN);
444                         }
445                 }
446
447         } else {
448                 omxFIMLSingleIterationOrdinal(off, off, 0, data->rows);
449         }
450
451         if(!returnRowLikelihoods) {
452                 double val, sum = 0.0;
453                 // floating-point addition is not associative,
454                 // so we serialized the following reduction operation.
455                 for(int i = 0; i < data->rows; i++) {
456                         val = omxVectorElement(ofiml->rowLogLikelihoods, i);
457 //                      mxLog("%d , %f, %llx\n", i, val, *((unsigned long long*) &val));
458                         sum += val;
459                 }       
460                 if(OMX_VERBOSE || OMX_DEBUG) {mxLog("Total Likelihood is %3.3f", sum);}
461                 omxSetMatrixElement(off->matrix, 0, 0, sum);
462         }
463 }
464
465 void omxInitFIMLFitFunction(omxFitFunction* off)
466 {
467         if(OMX_DEBUG) {
468                 mxLog("Initializing FIML fit function function.");
469         }
470         SEXP rObj = off->rObj;
471
472         int numOrdinal = 0, numContinuous = 0;
473         omxMatrix *cov, *means;
474
475         omxFIMLFitFunction *newObj = (omxFIMLFitFunction*) R_alloc(1, sizeof(omxFIMLFitFunction));
476         omxExpectation* expectation = off->expectation;
477         if(expectation == NULL) {
478                 omxRaiseError(off->matrix->currentState, -1, "FIML cannot fit without model expectations.");
479                 return;
480         }
481
482         cov = omxGetExpectationComponent(expectation, off, "cov");
483         if(cov == NULL) { 
484                 omxRaiseError(off->matrix->currentState, -1, "No covariance expectation in FIML evaluation.");
485                 return;
486         }
487
488         means = omxGetExpectationComponent(expectation, off, "means");
489         
490         if(means == NULL) { 
491                 omxRaiseError(off->matrix->currentState, -1, "No means model in FIML evaluation.");
492                 return;
493         }
494
495         if(OMX_DEBUG) {
496                 mxLog("FIML Initialization Completed.");
497         }
498         
499     newObj->cov = cov;
500     newObj->means = means;
501     newObj->smallMeans = NULL;
502     newObj->ordMeans   = NULL;
503     newObj->contRow    = NULL;
504     newObj->ordRow     = NULL;
505     newObj->ordCov     = NULL;
506     newObj->ordContCov = NULL;
507     newObj->halfCov    = NULL;
508     newObj->reduceCov  = NULL;
509     
510     /* Set default FitFunction calls to FIML FitFunction Calls */
511         off->computeFun = omxCallFIMLFitFunction;
512         off->fitType = "imxFitFunctionFIML";
513         off->setFinalReturns = omxSetFinalReturnsFIMLFitFunction;
514         off->destructFun = omxDestroyFIMLFitFunction;
515         off->populateAttrFun = omxPopulateFIMLAttributes;
516
517         off->usesChildModels = TRUE;
518
519         if(OMX_DEBUG) {
520                 mxLog("Accessing data source.");
521         }
522         newObj->data = off->expectation->data;
523
524         if(OMX_DEBUG) {
525                 mxLog("Accessing row likelihood option.");
526         }
527         newObj->returnRowLikelihoods = Rf_asInteger(R_do_slot(rObj, Rf_install("vector")));
528         if(newObj->returnRowLikelihoods) {
529                 omxResizeMatrix(off->matrix, newObj->data->rows, 1, FALSE);
530         }
531     newObj->rowLikelihoods = omxInitMatrix(NULL, newObj->data->rows, 1, TRUE, off->matrix->currentState);
532     newObj->rowLogLikelihoods = omxInitMatrix(NULL, newObj->data->rows, 1, TRUE, off->matrix->currentState);
533
534         if(OMX_DEBUG) {
535                 mxLog("Accessing variable mapping structure.");
536         }
537         newObj->dataColumns = off->expectation->dataColumns;
538
539         if(OMX_DEBUG) {
540                 mxLog("Accessing Threshold matrix.");
541         }
542         newObj->thresholdCols = off->expectation->thresholds;
543         numOrdinal = off->expectation->numOrdinal;
544         numContinuous = newObj->dataColumns->cols - off->expectation->numOrdinal;
545
546         omxSetContiguousDataColumns(&(newObj->contiguous), newObj->data, newObj->dataColumns);
547         
548         newObj->numDefs = off->expectation->numDefs;
549         newObj->defVars = off->expectation->defVars;
550         newObj->oldDefs = (double *) R_alloc(newObj->numDefs, sizeof(double));          // Storage for Def Vars
551
552         if(OMX_DEBUG) {
553                 mxLog("Accessing definition variables structure.");
554         }
555         newObj->oldDefs = (double *) R_alloc(newObj->numDefs, sizeof(double));          // Storage for Def Vars
556         memset(newObj->oldDefs, NA_REAL, sizeof(double) * newObj->numDefs);                     // Does this work?
557         // for(nextDef = 0; nextDef < newObj->numDefs; nextDef++) {
558         //      newObj->oldDefs[nextDef] = NA_REAL;                                     // Def Vars default to NA
559         // }
560
561     /* Temporary storage for calculation */
562     int covCols = newObj->cov->cols;
563         if(OMX_DEBUG){mxLog("Number of columns found is %d", covCols);}
564     // int ordCols = omxDataNumFactor(newObj->data);        // Unneeded, since we don't use it.
565     // int contCols = omxDataNumNumeric(newObj->data);
566     newObj->smallRow = omxInitMatrix(NULL, 1, covCols, TRUE, off->matrix->currentState);
567     newObj->smallCov = omxInitMatrix(NULL, covCols, covCols, TRUE, off->matrix->currentState);
568     newObj->RCX = omxInitMatrix(NULL, 1, covCols, TRUE, off->matrix->currentState);
569 //  newObj->zeros = omxInitMatrix(NULL, 1, newObj->cov->cols, TRUE, off->matrix->currentState);
570
571     omxAliasMatrix(newObj->smallCov, newObj->cov);          // Will keep its aliased state from here on.
572     off->argStruct = (void*)newObj;
573
574     if(numOrdinal > 0 && numContinuous <= 0) {
575         if(OMX_DEBUG) {
576             mxLog("Ordinal Data detected.  Using Ordinal FIML.");
577         }
578         newObj->weights = (double*) R_alloc(covCols, sizeof(double));
579         newObj->smallMeans = omxInitMatrix(NULL, covCols, 1, TRUE, off->matrix->currentState);
580         omxAliasMatrix(newObj->smallMeans, newObj->means);
581         newObj->corList = (double*) R_alloc(covCols * (covCols + 1) / 2, sizeof(double));
582         newObj->smallCor = (double*) R_alloc(covCols * (covCols + 1) / 2, sizeof(double));
583         newObj->lThresh = (double*) R_alloc(covCols, sizeof(double));
584         newObj->uThresh = (double*) R_alloc(covCols, sizeof(double));
585         newObj->Infin = (int*) R_alloc(covCols, sizeof(int));
586
587         off->computeFun = omxCallFIMLOrdinalFitFunction;
588     } else if(numOrdinal > 0) {
589         if(OMX_DEBUG) {
590             mxLog("Ordinal and Continuous Data detected.  Using Joint Ordinal/Continuous FIML.");
591         }
592
593         newObj->weights = (double*) R_alloc(covCols, sizeof(double));
594         newObj->smallMeans = omxInitMatrix(NULL, covCols, 1, TRUE, off->matrix->currentState);
595         newObj->ordMeans = omxInitMatrix(NULL, covCols, 1, TRUE, off->matrix->currentState);
596         newObj->contRow = omxInitMatrix(NULL, covCols, 1, TRUE, off->matrix->currentState);
597         newObj->ordRow = omxInitMatrix(NULL, covCols, 1, TRUE, off->matrix->currentState);
598         newObj->ordCov = omxInitMatrix(NULL, covCols, covCols, TRUE, off->matrix->currentState);
599         newObj->ordContCov = omxInitMatrix(NULL, covCols, covCols, TRUE, off->matrix->currentState);
600         newObj->halfCov = omxInitMatrix(NULL, covCols, covCols, TRUE, off->matrix->currentState);
601         newObj->reduceCov = omxInitMatrix(NULL, covCols, covCols, TRUE, off->matrix->currentState);
602         omxAliasMatrix(newObj->smallMeans, newObj->means);
603         omxAliasMatrix(newObj->ordMeans, newObj->means);
604         omxAliasMatrix(newObj->contRow, newObj->smallRow );
605         omxAliasMatrix(newObj->ordRow, newObj->smallRow );
606         omxAliasMatrix(newObj->ordCov, newObj->cov);
607         omxAliasMatrix(newObj->ordContCov, newObj->cov);
608         omxAliasMatrix(newObj->smallMeans, newObj->means);
609         newObj->corList = (double*) R_alloc(covCols * (covCols + 1) / 2, sizeof(double));
610         newObj->lThresh = (double*) R_alloc(covCols, sizeof(double));
611         newObj->uThresh = (double*) R_alloc(covCols, sizeof(double));
612         newObj->Infin = (int*) R_alloc(covCols, sizeof(int));
613
614         off->computeFun = omxCallJointFIMLFitFunction;
615     }
616 }