globle intBool EnvSetAutoFloatDividend( void *theEnv, int value) { int ov; ov = BasicMathFunctionData(theEnv)->AutoFloatDividend; BasicMathFunctionData(theEnv)->AutoFloatDividend = value; return(ov); }
globle void BasicMathFunctionDefinitions( void *theEnv) { AllocateEnvironmentData(theEnv,BMATHFUN_DATA,sizeof(struct basicMathFunctionData),NULL); BasicMathFunctionData(theEnv)->AutoFloatDividend = TRUE; #if ! RUN_TIME EnvDefineFunction2(theEnv,"+", 'n',PTIEF AdditionFunction, "AdditionFunction", "2*n"); EnvDefineFunction2(theEnv,"*", 'n', PTIEF MultiplicationFunction, "MultiplicationFunction", "2*n"); EnvDefineFunction2(theEnv,"-", 'n', PTIEF SubtractionFunction, "SubtractionFunction", "2*n"); EnvDefineFunction2(theEnv,"/", 'n', PTIEF DivisionFunction, "DivisionFunction", "2*n"); EnvDefineFunction2(theEnv,"div", 'l', PTIEF DivFunction, "DivFunction", "2*n"); EnvDefineFunction2(theEnv,"set-auto-float-dividend", 'b', SetAutoFloatDividendCommand, "SetAutoFloatDividendCommand", "11"); EnvDefineFunction2(theEnv,"get-auto-float-dividend", 'b', GetAutoFloatDividendCommand, "GetAutoFloatDividendCommand", "00"); EnvDefineFunction2(theEnv,"integer", 'l', PTIEF IntegerFunction, "IntegerFunction", "11n"); EnvDefineFunction2(theEnv,"float", 'd', PTIEF FloatFunction, "FloatFunction", "11n"); EnvDefineFunction2(theEnv,"abs", 'n', PTIEF AbsFunction, "AbsFunction", "11n"); EnvDefineFunction2(theEnv,"min", 'n', PTIEF MinFunction, "MinFunction", "2*n"); EnvDefineFunction2(theEnv,"max", 'n', PTIEF MaxFunction, "MaxFunction", "2*n"); #endif }
globle int GetAutoFloatDividendCommand( void *theEnv) { /*============================================*/ /* Check for the correct number of arguments. */ /*============================================*/ EnvArgCountCheck(theEnv,"get-auto-float-dividend",EXACTLY,0); /*=============================*/ /* Return the current setting. */ /*=============================*/ return(BasicMathFunctionData(theEnv)->AutoFloatDividend); }
globle int SetAutoFloatDividendCommand( void *theEnv) { int oldValue; DATA_OBJECT theArgument; /*===============================*/ /* Remember the present setting. */ /*===============================*/ oldValue = BasicMathFunctionData(theEnv)->AutoFloatDividend; /*============================================*/ /* Check for the correct number of arguments. */ /*============================================*/ if (EnvArgCountCheck(theEnv,"set-auto-float-dividend",EXACTLY,1) == -1) { return(oldValue); } EnvRtnUnknown(theEnv,1,&theArgument); /*============================================================*/ /* The symbol FALSE disables the auto float dividend feature. */ /*============================================================*/ if ((theArgument.value == EnvFalseSymbol(theEnv)) && (theArgument.type == SYMBOL)) { BasicMathFunctionData(theEnv)->AutoFloatDividend = FALSE; } else { BasicMathFunctionData(theEnv)->AutoFloatDividend = TRUE; } /*======================================*/ /* Return the old value of the feature. */ /*======================================*/ return(oldValue); }
globle intBool EnvGetAutoFloatDividend( void *theEnv) { return(BasicMathFunctionData(theEnv)->AutoFloatDividend); }
globle void DivisionFunction( void *theEnv, DATA_OBJECT_PTR returnValue) { double ftotal = 1.0; long ltotal = 1L; intBool useFloatTotal; EXPRESSION *theExpression; DATA_OBJECT theArgument; int pos = 1; useFloatTotal = BasicMathFunctionData(theEnv)->AutoFloatDividend; /*===================================================*/ /* Get the first argument. This number which will be */ /* the starting product from which all subsequent */ /* arguments will divide. If the auto float dividend */ /* feature is enable, then this number is converted */ /* to a float if it is an integer. */ /*===================================================*/ theExpression = GetFirstArgument(); if (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"/",&theArgument,useFloatTotal,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); if (theArgument.type == INTEGER) { ltotal = ValueToLong(theArgument.value); } else { ftotal = ValueToDouble(theArgument.value); useFloatTotal = TRUE; } pos++; } /*====================================================*/ /* Loop through each of the arguments dividing it */ /* into a running product. If a floating point number */ /* is encountered, then do all subsequent operations */ /* using floating point values. Each argument is */ /* checked to prevent a divide by zero error. */ /*====================================================*/ while (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"/",&theArgument,useFloatTotal,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); if ((theArgument.type == INTEGER) ? (ValueToLong(theArgument.value) == 0L) : ((theArgument.type == FLOAT) ? ValueToDouble(theArgument.value) == 0.0 : FALSE)) { DivideByZeroErrorMessage(theEnv,"/"); SetHaltExecution(theEnv,TRUE); SetEvaluationError(theEnv,TRUE); returnValue->type = FLOAT; returnValue->value = (void *) EnvAddDouble(theEnv,1.0); return; } if (useFloatTotal) { ftotal /= ValueToDouble(theArgument.value); } else { if (theArgument.type == INTEGER) { ltotal /= ValueToLong(theArgument.value); } else { ftotal = (double) ltotal / ValueToDouble(theArgument.value); useFloatTotal = TRUE; } } pos++; } /*======================================================*/ /* If a floating point number was in the argument list, */ /* then return a float, otherwise return an integer. */ /*======================================================*/ if (useFloatTotal) { returnValue->type = FLOAT; returnValue->value = (void *) EnvAddDouble(theEnv,ftotal); } else { returnValue->type = INTEGER; returnValue->value = (void *) EnvAddLong(theEnv,ltotal); } }
globle CLIPS_BOOLEAN EnvGetAutoFloatDividend( void *theEnv) { return(BasicMathFunctionData(theEnv)->AutoFloatDividend); }