globle void AdditionFunction( void *theEnv, DATA_OBJECT_PTR returnValue) { double ftotal = 0.0; long ltotal = 0L; intBool useFloatTotal = FALSE; EXPRESSION *theExpression; DATA_OBJECT theArgument; int pos = 1; /*=================================================*/ /* Loop through each of the arguments adding it to */ /* a running total. If a floating point number is */ /* encountered, then do all subsequent operations */ /* using floating point values. */ /*=================================================*/ theExpression = GetFirstArgument(); while (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"+",&theArgument,useFloatTotal,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); 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 intBool NumericNotEqualFunction( void *theEnv, EXEC_STATUS) { EXPRESSION *theArgument; DATA_OBJECT rv1, rv2; int pos = 1; /*=========================*/ /* Get the first argument. */ /*=========================*/ theArgument = GetFirstArgument(); if (theArgument == NULL) { return(TRUE); } if (! GetNumericArgument(theEnv,execStatus,theArgument,"<>",&rv1,FALSE,pos)) return(FALSE); pos++; /*=================================================*/ /* Compare each of the subsequent arguments to the */ /* first. If any is equal, then return FALSE. */ /*=================================================*/ for (theArgument = GetNextArgument(theArgument); theArgument != NULL; theArgument = GetNextArgument(theArgument), pos++) { if (! GetNumericArgument(theEnv,execStatus,theArgument,"<>",&rv2,FALSE,pos)) return(FALSE); if (rv1.type == INTEGER) { if (rv2.type == INTEGER) { if (ValueToLong(rv1.value) == ValueToLong(rv2.value)) { return(FALSE); } } else { if ((double) ValueToLong(rv1.value) == ValueToDouble(rv2.value)) { return(FALSE); } } } else { if (rv2.type == INTEGER) { if (ValueToDouble(rv1.value) == (double) ValueToLong(rv2.value)) { return(FALSE); } } else { if (ValueToDouble(rv1.value) == ValueToDouble(rv2.value)) { return(FALSE); } } } } /*===================================*/ /* All arguments were unequal to the */ /* first argument. Return TRUE. */ /*===================================*/ return(TRUE); }
globle intBool GreaterThanFunction( void *theEnv, EXEC_STATUS) { EXPRESSION *theArgument; DATA_OBJECT rv1, rv2; int pos = 1; /*=========================*/ /* Get the first argument. */ /*=========================*/ theArgument = GetFirstArgument(); if (theArgument == NULL) { return(TRUE); } if (! GetNumericArgument(theEnv,execStatus,theArgument,">",&rv1,FALSE,pos)) return(FALSE); pos++; /*==========================================*/ /* Compare each of the subsequent arguments */ /* to its predecessor. If any is lesser or */ /* equal, then return FALSE. */ /*==========================================*/ for (theArgument = GetNextArgument(theArgument); theArgument != NULL; theArgument = GetNextArgument(theArgument), pos++) { if (! GetNumericArgument(theEnv,execStatus,theArgument,">",&rv2,FALSE,pos)) return(FALSE); if (rv1.type == INTEGER) { if (rv2.type == INTEGER) { if (ValueToLong(rv1.value) <= ValueToLong(rv2.value)) { return(FALSE); } } else { if ((double) ValueToLong(rv1.value) <= ValueToDouble(rv2.value)) { return(FALSE); } } } else { if (rv2.type == INTEGER) { if (ValueToDouble(rv1.value) <= (double) ValueToLong(rv2.value)) { return(FALSE); } } else { if (ValueToDouble(rv1.value) <= ValueToDouble(rv2.value)) { return(FALSE); } } } rv1.type = rv2.type; rv1.value = rv2.value; } /*================================*/ /* Each argument was greater than */ /* its predecessor. Return TRUE. */ /*================================*/ return(TRUE); }
globle long DivFunction( void *theEnv) { long total = 1L; EXPRESSION *theExpression; DATA_OBJECT theArgument; int pos = 1; long theNumber; /*===================================================*/ /* Get the first argument. This number which will be */ /* the starting product from which all subsequent */ /* arguments will divide. */ /*===================================================*/ theExpression = GetFirstArgument(); if (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"div",&theArgument,FALSE,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); if (theArgument.type == INTEGER) { total = ValueToLong(theArgument.value); } else { total = (long) ValueToDouble(theArgument.value); } pos++; } /*=====================================================*/ /* Loop through each of the arguments dividing it into */ /* a running product. Floats are converted to integers */ /* and each argument is checked to prevent a divide by */ /* zero error. */ /*=====================================================*/ while (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"div",&theArgument,FALSE,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); if (theArgument.type == INTEGER) theNumber = ValueToLong(theArgument.value); else if (theArgument.type == FLOAT) theNumber = (long) ValueToDouble(theArgument.value); else theNumber = 1; if (theNumber == 0L) { DivideByZeroErrorMessage(theEnv,"div"); SetHaltExecution(theEnv,TRUE); SetEvaluationError(theEnv,TRUE); return(1L); } if (theArgument.type == INTEGER) { total /= ValueToLong(theArgument.value); } else { total = total / (long) ValueToDouble(theArgument.value); } pos++; } /*======================================================*/ /* The result of the div function is always an integer. */ /*======================================================*/ return(total); }
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 void MultiplicationFunction( void *theEnv, DATA_OBJECT_PTR returnValue) { double ftotal = 1.0; double ftmp = 0.0; long long ltotal = 1LL; long long ltmp = 0LL; intBool useFloatTotal = FALSE; EXPRESSION *theExpression; DATA_OBJECT theArgument; int pos = 1; /*===================================================*/ /* Loop through each of the arguments multiplying it */ /* by a running product. If a floating point number */ /* is encountered, then do all subsequent operations */ /* using floating point values. */ /*===================================================*/ theExpression = GetFirstArgument(); while (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"*",&theArgument,useFloatTotal,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); if (useFloatTotal) { ftmp = ValueToDouble(theArgument.value); if(ftmp == 0.0) { ftotal = 0.0; break; } else if(ftmp != 1.0) { ftotal *= ftmp; } } else { if (theArgument.type == INTEGER) { ltmp = ValueToLong(theArgument.value); if(ltmp == 0LL) { ltotal = 0LL; break; } else if (ltmp != 1LL) { /* We shouldn't waste time handling multiplication by one */ ltotal *= ltmp; } } else { ftmp = ValueToDouble(theArgument.value); if(ftmp == 0.0) { ftotal = 0.0; break; } else if(ftmp == 1.0) { /* just cast as a double instead of wasting a multiply */ ftotal = (double) ltotal; } else { ftotal = (double) ltotal * ftmp; } 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 intBool LessThanOrEqualFunction( void *theEnv) { EXPRESSION *theArgument; DATA_OBJECT rv1, rv2; int pos = 1; /*=========================*/ /* Get the first argument. */ /*=========================*/ theArgument = GetFirstArgument(); if (theArgument == NULL) { return(TRUE); } if (! GetNumericArgument(theEnv,theArgument,"<=",&rv1,FALSE,pos)) return(FALSE); pos++; /*====================================================*/ /* Compare each of the subsequent arguments to its */ /* predecessor. If any is greater, then return FALSE. */ /*====================================================*/ for (theArgument = GetNextArgument(theArgument); theArgument != NULL; theArgument = GetNextArgument(theArgument), pos++) { if (! GetNumericArgument(theEnv,theArgument,"<=",&rv2,FALSE,pos)) return(FALSE); if (rv1.type == INTEGER) { if (rv2.type == INTEGER) { if (ValueToLong(rv1.value) > ValueToLong(rv2.value)) { return(FALSE); } } else { if ((double) ValueToLong(rv1.value) > ValueToDouble(rv2.value)) { return(FALSE); } } } else { if (rv2.type == INTEGER) { if (ValueToDouble(rv1.value) > (double) ValueToLong(rv2.value)) { return(FALSE); } } else { if (ValueToDouble(rv1.value) > ValueToDouble(rv2.value)) { return(FALSE); } } } rv1.type = rv2.type; rv1.value = rv2.value; } /*======================================*/ /* Each argument was less than or equal */ /* to it predecessor. Return TRUE. */ /*======================================*/ return(TRUE); }
globle void SubtractionFunction( void *theEnv, DATA_OBJECT_PTR returnValue) { double ftotal = 0.0; long ltotal = 0L; BOOLEAN useFloatTotal = FALSE; EXPRESSION *theExpression; DATA_OBJECT theArgument; int pos = 1; /*=================================================*/ /* Get the first argument. This number which will */ /* be the starting total from which all subsequent */ /* arguments will subtracted. */ /*=================================================*/ 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 subtracting it */ /* from a running total. If a floating point number */ /* is encountered, then do all subsequent operations */ /* using floating point values. */ /*===================================================*/ while (theExpression != NULL) { if (! GetNumericArgument(theEnv,theExpression,"-",&theArgument,useFloatTotal,pos)) theExpression = NULL; else theExpression = GetNextArgument(theExpression); 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); } }