📄 bmathfun.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* BASIC MATH FUNCTIONS MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Contains the code for numerous basic math */
/* functions including +, *, -, /, integer, float, div, */
/* abs,set-auto-float-dividend, get-auto-float-dividend, */
/* min, and max. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/*************************************************************/
#define _BMATHFUN_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include "setup.h"
#include "argacces.h"
#include "envrnmnt.h"
#include "exprnpsr.h"
#include "router.h"
#include "bmathfun.h"
#define BMATHFUN_DATA 6
struct basicMathFunctionData
{
intBool AutoFloatDividend;
};
#define BasicMathFunctionData(theEnv) ((struct basicMathFunctionData *) GetEnvironmentData(theEnv,BMATHFUN_DATA))
/***************************************************************/
/* BasicMathFunctionDefinitions: Defines basic math functions. */
/***************************************************************/
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
}
/**********************************/
/* AdditionFunction: H/L access */
/* routine for the + function. */
/**********************************/
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);
}
}
/****************************************/
/* MultiplicationFunction: CLIPS access */
/* routine for the * function. */
/****************************************/
globle void MultiplicationFunction(
void *theEnv,
DATA_OBJECT_PTR returnValue)
{
double ftotal = 1.0;
long ltotal = 1L;
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)
{ 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);
}
}
/*************************************/
/* SubtractionFunction: CLIPS access */
/* routine for the - function. */
/*************************************/
globle void SubtractionFunction(
void *theEnv,
DATA_OBJECT_PTR returnValue)
{
double ftotal = 0.0;
long ltotal = 0L;
intBool 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);
}
}
/***********************************/
/* DivisionFunction: CLIPS access */
/* routine for the / function. */
/***********************************/
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);
}
}
/*************************************/
/* DivFunction: H/L access routine */
/* for the div function. */
/*************************************/
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++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -