<commit_before>/*
 *  Copyright 2007-2012 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */


/***********************************************************
* 
*  omxAlgebra.cc
*
*  Created: <NAME> 	Date: 2008-11-13 12:33:06
*
*	Algebras are a subclass of data matrix that evaluates
*   itself anew at each iteration, so that any changes to
*   free parameters can be incorporated into the update.
*
**********************************************************/

#include "omxMatrix.h"

omxMatrix* omxInitAlgebra(omxAlgebra *oa, omxState* os) {

	omxMatrix* om = omxInitMatrix(NULL, 0, 0, TRUE, os);
	
	omxInitAlgebraWithMatrix(oa, om);

	return om;
}

void omxInitAlgebraWithMatrix(omxAlgebra *oa, omxMatrix *om) {
	
	if(oa == NULL) {
		oa = (omxAlgebra*) R_alloc(1, sizeof(omxAlgebra));
	}
	
	if(OMX_DEBUG && om->currentState->parentState == NULL) { 
		Rprintf("Initializing algebra 0x%0x with 0x%0x.\n", oa, om);
	}
	
	oa->args = NULL;
	oa->funWrapper = NULL;
	oa->numArgs = 0;
	oa->matrix = om;
	om->algebra = oa;

}

void omxDuplicateAlgebra(omxMatrix* tgt, omxMatrix* src, omxState* newState) {

    if(src->algebra != NULL) {
		omxFillMatrixFromMxAlgebra(tgt, src->algebra->sexpAlgebra, src->name);
    } else if(src->objective != NULL) {
        omxDuplicateObjectiveMatrix(tgt, src, newState);
    }

}

void omxFreeAlgebraArgs(omxAlgebra *oa) {
	/* Completely destroy the algebra tree */
	
	if(OMX_DEBUG) { 
	    Rprintf("Freeing algebra at 0x%0x with %d args.\n", 
	        oa, oa->numArgs); 
	}
	
	int j;
	for(j = 0; j < oa->numArgs; j++) {
	    if(OMX_DEBUG) { 
    	    Rprintf("Freeing argument %d at 0x%0x.\n", 
    	        j, oa->args[j]);
    	}
		omxFreeAllMatrixData(oa->args[j]);
		oa->args[j] = NULL;
	}
	oa->numArgs = 0;
	oa->matrix = NULL;
}

void omxAlgebraCompute(omxAlgebra *oa) {
	if(OMX_DEBUG_ALGEBRA) { 
		Rprintf("Algebra compute (%s): 0x%0x (needed: %d/%d).\n", 
			oa->matrix->name, oa->matrix, 
			oa->matrix->lastCompute, oa->matrix->currentState->computeCount);
	}
		
	for(int j = 0; j < oa->numArgs; j++) {
		if(OMX_DEBUG_ALGEBRA) { Rprintf("Recomputing arg %d at 0x%0x (Which %s need it).\n", j, oa->args[j], (omxNeedsUpdate(oa->args[j])?"does":"does not")); }
		omxRecompute(oa->args[j]);
	}
   // Recompute happens in handleFreeVars, for now.
	
	if(oa->funWrapper == NULL) { 			// No-op algebra: only for algebra-is-a-matrix condition.
		if(oa->numArgs == 1) {
			if(OMX_DEBUG_ALGEBRA) { omxPrint(oa->args[0], "No-op Matrix"); }
			omxCopyMatrix(oa->matrix, oa->args[0]);
		} else {
			error("Internal Error: Empty algebra evaluated.\n");
		}
	} else {
		if(OMX_DEBUG_ALGEBRA) { Rprintf("Activating function with %d args.\n", oa->numArgs); }
		(*((void(*)(omxMatrix**, int, omxMatrix*))oa->funWrapper))(oa->args, (oa->numArgs), oa->matrix);
	}
	omxMatrixCompute(oa->matrix);
	
	if(OMX_DEBUG_ALGEBRA) { omxAlgebraPrint(oa, "Result is"); }
}

int omxAlgebraNeedsUpdate(omxAlgebra *oa)
{
	if(OMX_DEBUG_ALGEBRA) {Rprintf("AlgebraNeedsUpdate:%d?", oa->numArgs);}
	for(int j = 0; j < fabs(oa->numArgs); j++) {
		if(omxNeedsUpdate(oa->args[j])) {
			if(OMX_DEBUG_ALGEBRA) {Rprintf("Arg %d Needs Update.\n");}
			return TRUE;
		}
	}
    return FALSE;
}

omxMatrix* omxNewMatrixFromMxAlgebra(SEXP alg, omxState* os, const char *name) {

	omxMatrix *om = omxInitMatrix(NULL, 0, 0, TRUE, os);<commit_msg>Minor performance improvements to omxAlgebraNeedsUpdate<commit_after>/*
 *  Copyright 2007-2012 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */


/***********************************************************
* 
*  omxAlgebra.cc
*
*  Created: <NAME> 	Date: 2008-11-13 12:33:06
*
*	Algebras are a subclass of data matrix that evaluates
*   itself anew at each iteration, so that any changes to
*   free parameters can be incorporated into the update.
*
**********************************************************/

#include "omxMatrix.h"

omxMatrix* omxInitAlgebra(omxAlgebra *oa, omxState* os) {

	omxMatrix* om = omxInitMatrix(NULL, 0, 0, TRUE, os);
	
	omxInitAlgebraWithMatrix(oa, om);

	return om;
}

void omxInitAlgebraWithMatrix(omxAlgebra *oa, omxMatrix *om) {
	
	if(oa == NULL) {
		oa = (omxAlgebra*) R_alloc(1, sizeof(omxAlgebra));
	}
	
	if(OMX_DEBUG && om->currentState->parentState == NULL) { 
		Rprintf("Initializing algebra 0x%0x with 0x%0x.\n", oa, om);
	}
	
	oa->args = NULL;
	oa->funWrapper = NULL;
	oa->numArgs = 0;
	oa->matrix = om;
	om->algebra = oa;

}

void omxDuplicateAlgebra(omxMatrix* tgt, omxMatrix* src, omxState* newState) {

    if(src->algebra != NULL) {
		omxFillMatrixFromMxAlgebra(tgt, src->algebra->sexpAlgebra, src->name);
    } else if(src->objective != NULL) {
        omxDuplicateObjectiveMatrix(tgt, src, newState);
    }

}

void omxFreeAlgebraArgs(omxAlgebra *oa) {
	/* Completely destroy the algebra tree */
	
	if(OMX_DEBUG) { 
	    Rprintf("Freeing algebra at 0x%0x with %d args.\n", 
	        oa, oa->numArgs); 
	}
	
	int j;
	for(j = 0; j < oa->numArgs; j++) {
	    if(OMX_DEBUG) { 
    	    Rprintf("Freeing argument %d at 0x%0x.\n", 
    	        j, oa->args[j]);
    	}
		omxFreeAllMatrixData(oa->args[j]);
		oa->args[j] = NULL;
	}
	oa->numArgs = 0;
	oa->matrix = NULL;
}

void omxAlgebraCompute(omxAlgebra *oa) {
	if(OMX_DEBUG_ALGEBRA) { 
		Rprintf("Algebra compute (%s): 0x%0x (needed: %d/%d).\n", 
			oa->matrix->name, oa->matrix, 
			oa->matrix->lastCompute, oa->matrix->currentState->computeCount);
	}
		
	for(int j = 0; j < oa->numArgs; j++) {
		if(OMX_DEBUG_ALGEBRA) { Rprintf("Recomputing arg %d at 0x%0x (Which %s need it).\n", j, oa->args[j], (omxNeedsUpdate(oa->args[j])?"does":"does not")); }
		omxRecompute(oa->args[j]);
	}
   // Recompute happens in handleFreeVars, for now.
	
	if(oa->funWrapper == NULL) { 			// No-op algebra: only for algebra-is-a-matrix condition.
		if(oa->numArgs == 1) {
			if(OMX_DEBUG_ALGEBRA) { omxPrint(oa->args[0], "No-op Matrix"); }
			omxCopyMatrix(oa->matrix, oa->args[0]);
		} else {
			error("Internal Error: Empty algebra evaluated.\n");
		}
	} else {
		if(OMX_DEBUG_ALGEBRA) { Rprintf("Activating function with %d args.\n", oa->numArgs); }
		(*((void(*)(omxMatrix**, int, omxMatrix*))oa->funWrapper))(oa->args, (oa->numArgs), oa->matrix);
	}
	omxMatrixCompute(oa->matrix);
	
	if(OMX_DEBUG_ALGEBRA) { omxAlgebraPrint(oa, "Result is"); }
}

int omxAlgebraNeedsUpdate(omxAlgebra *oa)
{
	int numArgs = oa->numArgs;
	omxMatrix **args = oa->args;

	if(OMX_DEBUG_ALGEBRA) {Rprintf("AlgebraNeedsUpdate:%d?", oa->numArgs);}
	for(int j = 0; j < numArgs; j++) {
		if(omxNeedsUpdate(args[j])) {
			if(OMX_DEBUG_ALGEBRA) {Rprintf("Arg %d Needs Update.\n");}
			return TRUE;
		}
	}
	return FALSE;
}

omxMatrix* omxNewMatrixFromMxAlgebra(SEXP alg, omxState* os, const char *name) {

	omxMatrix *om = omxInitMatrix(NULL, 0, 0, TRUE, os);
{'fraction_non_alphanumeric': 0.17951991828396321, 'fraction_numerical': 0.013023493360572012, 'mean_word_length': 3.941955835962145, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4578565', 'n_tokens_mistral': 3133, 'n_tokens_neox': 2919, 'n_words': 693}