00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define _BMATHFUN_SOURCE_
00028
00029 #include <stdio.h>
00030 #define _STDIO_INCLUDED_
00031
00032 #include "setup.h"
00033
00034 #include "argacces.h"
00035 #include "envrnmnt.h"
00036 #include "exprnpsr.h"
00037 #include "router.h"
00038
00039 #include "bmathfun.h"
00040
00041 #define BMATHFUN_DATA 6
00042
00043 struct basicMathFunctionData
00044 {
00045 intBool AutoFloatDividend;
00046 };
00047
00048 #define BasicMathFunctionData(theEnv) ((struct basicMathFunctionData *) GetEnvironmentData(theEnv,BMATHFUN_DATA))
00049
00050
00051
00052
00053 globle void BasicMathFunctionDefinitions(
00054 void *theEnv)
00055 {
00056 AllocateEnvironmentData(theEnv,BMATHFUN_DATA,sizeof(struct basicMathFunctionData),NULL);
00057
00058 BasicMathFunctionData(theEnv)->AutoFloatDividend = TRUE;
00059
00060 #if ! RUN_TIME
00061 EnvDefineFunction2(theEnv,"+", 'n',PTIEF AdditionFunction, "AdditionFunction", "2*n");
00062 EnvDefineFunction2(theEnv,"*", 'n', PTIEF MultiplicationFunction, "MultiplicationFunction", "2*n");
00063 EnvDefineFunction2(theEnv,"-", 'n', PTIEF SubtractionFunction, "SubtractionFunction", "2*n");
00064
00065 EnvDefineFunction2(theEnv,"/", 'n', PTIEF DivisionFunction, "DivisionFunction", "2*n");
00066 EnvDefineFunction2(theEnv,"div", 'g', PTIEF DivFunction, "DivFunction", "2*n");
00067 EnvDefineFunction2(theEnv,"set-auto-float-dividend", 'b',
00068 SetAutoFloatDividendCommand, "SetAutoFloatDividendCommand", "11");
00069 EnvDefineFunction2(theEnv,"get-auto-float-dividend", 'b',
00070 GetAutoFloatDividendCommand, "GetAutoFloatDividendCommand", "00");
00071
00072 EnvDefineFunction2(theEnv,"integer", 'g', PTIEF IntegerFunction, "IntegerFunction", "11n");
00073 EnvDefineFunction2(theEnv,"float", 'd', PTIEF FloatFunction, "FloatFunction", "11n");
00074 EnvDefineFunction2(theEnv,"abs", 'n', PTIEF AbsFunction, "AbsFunction", "11n");
00075 EnvDefineFunction2(theEnv,"min", 'n', PTIEF MinFunction, "MinFunction", "2*n");
00076 EnvDefineFunction2(theEnv,"max", 'n', PTIEF MaxFunction, "MaxFunction", "2*n");
00077 #endif
00078 }
00079
00080
00081
00082
00083
00084 globle void AdditionFunction(
00085 void *theEnv,
00086 DATA_OBJECT_PTR returnValue)
00087 {
00088 double ftotal = 0.0;
00089 long long ltotal = 0LL;
00090 intBool useFloatTotal = FALSE;
00091 EXPRESSION *theExpression;
00092 DATA_OBJECT theArgument;
00093 int pos = 1;
00094
00095
00096
00097
00098
00099
00100
00101
00102 theExpression = GetFirstArgument();
00103
00104 while (theExpression != NULL)
00105 {
00106 if (! GetNumericArgument(theEnv,theExpression,"+",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00107 else theExpression = GetNextArgument(theExpression);
00108
00109 if (useFloatTotal)
00110 { ftotal += ValueToDouble(theArgument.value); }
00111 else
00112 {
00113 if (theArgument.type == INTEGER)
00114 { ltotal += ValueToLong(theArgument.value); }
00115 else
00116 {
00117 ftotal = (double) ltotal + ValueToDouble(theArgument.value);
00118 useFloatTotal = TRUE;
00119 }
00120 }
00121
00122 pos++;
00123 }
00124
00125
00126
00127
00128
00129
00130 if (useFloatTotal)
00131 {
00132 returnValue->type = FLOAT;
00133 returnValue->value = (void *) EnvAddDouble(theEnv,ftotal);
00134 }
00135 else
00136 {
00137 returnValue->type = INTEGER;
00138 returnValue->value = (void *) EnvAddLong(theEnv,ltotal);
00139 }
00140 }
00141
00142
00143
00144
00145
00146 globle void MultiplicationFunction(
00147 void *theEnv,
00148 DATA_OBJECT_PTR returnValue)
00149 {
00150 double ftotal = 1.0;
00151 long long ltotal = 1LL;
00152 intBool useFloatTotal = FALSE;
00153 EXPRESSION *theExpression;
00154 DATA_OBJECT theArgument;
00155 int pos = 1;
00156
00157
00158
00159
00160
00161
00162
00163
00164 theExpression = GetFirstArgument();
00165
00166 while (theExpression != NULL)
00167 {
00168 if (! GetNumericArgument(theEnv,theExpression,"*",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00169 else theExpression = GetNextArgument(theExpression);
00170
00171 if (useFloatTotal)
00172 { ftotal *= ValueToDouble(theArgument.value); }
00173 else
00174 {
00175 if (theArgument.type == INTEGER)
00176 { ltotal *= ValueToLong(theArgument.value); }
00177 else
00178 {
00179 ftotal = (double) ltotal * ValueToDouble(theArgument.value);
00180 useFloatTotal = TRUE;
00181 }
00182 }
00183 pos++;
00184 }
00185
00186
00187
00188
00189
00190
00191 if (useFloatTotal)
00192 {
00193 returnValue->type = FLOAT;
00194 returnValue->value = (void *) EnvAddDouble(theEnv,ftotal);
00195 }
00196 else
00197 {
00198 returnValue->type = INTEGER;
00199 returnValue->value = (void *) EnvAddLong(theEnv,ltotal);
00200 }
00201 }
00202
00203
00204
00205
00206
00207 globle void SubtractionFunction(
00208 void *theEnv,
00209 DATA_OBJECT_PTR returnValue)
00210 {
00211 double ftotal = 0.0;
00212 long long ltotal = 0LL;
00213 intBool useFloatTotal = FALSE;
00214 EXPRESSION *theExpression;
00215 DATA_OBJECT theArgument;
00216 int pos = 1;
00217
00218
00219
00220
00221
00222
00223
00224 theExpression = GetFirstArgument();
00225 if (theExpression != NULL)
00226 {
00227 if (! GetNumericArgument(theEnv,theExpression,"-",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00228 else theExpression = GetNextArgument(theExpression);
00229
00230 if (theArgument.type == INTEGER)
00231 { ltotal = ValueToLong(theArgument.value); }
00232 else
00233 {
00234 ftotal = ValueToDouble(theArgument.value);
00235 useFloatTotal = TRUE;
00236 }
00237 pos++;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 while (theExpression != NULL)
00248 {
00249 if (! GetNumericArgument(theEnv,theExpression,"-",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00250 else theExpression = GetNextArgument(theExpression);
00251
00252 if (useFloatTotal)
00253 { ftotal -= ValueToDouble(theArgument.value); }
00254 else
00255 {
00256 if (theArgument.type == INTEGER)
00257 { ltotal -= ValueToLong(theArgument.value); }
00258 else
00259 {
00260 ftotal = (double) ltotal - ValueToDouble(theArgument.value);
00261 useFloatTotal = TRUE;
00262 }
00263 }
00264 pos++;
00265 }
00266
00267
00268
00269
00270
00271
00272 if (useFloatTotal)
00273 {
00274 returnValue->type = FLOAT;
00275 returnValue->value = (void *) EnvAddDouble(theEnv,ftotal);
00276 }
00277 else
00278 {
00279 returnValue->type = INTEGER;
00280 returnValue->value = (void *) EnvAddLong(theEnv,ltotal);
00281 }
00282 }
00283
00284
00285
00286
00287
00288 globle void DivisionFunction(
00289 void *theEnv,
00290 DATA_OBJECT_PTR returnValue)
00291 {
00292 double ftotal = 1.0;
00293 long long ltotal = 1LL;
00294 intBool useFloatTotal;
00295 EXPRESSION *theExpression;
00296 DATA_OBJECT theArgument;
00297 int pos = 1;
00298
00299 useFloatTotal = BasicMathFunctionData(theEnv)->AutoFloatDividend;
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 theExpression = GetFirstArgument();
00310 if (theExpression != NULL)
00311 {
00312 if (! GetNumericArgument(theEnv,theExpression,"/",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00313 else theExpression = GetNextArgument(theExpression);
00314
00315 if (theArgument.type == INTEGER)
00316 { ltotal = ValueToLong(theArgument.value); }
00317 else
00318 {
00319 ftotal = ValueToDouble(theArgument.value);
00320 useFloatTotal = TRUE;
00321 }
00322 pos++;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 while (theExpression != NULL)
00334 {
00335 if (! GetNumericArgument(theEnv,theExpression,"/",&theArgument,useFloatTotal,pos)) theExpression = NULL;
00336 else theExpression = GetNextArgument(theExpression);
00337
00338 if ((theArgument.type == INTEGER) ? (ValueToLong(theArgument.value) == 0L) :
00339 ((theArgument.type == FLOAT) ? ValueToDouble(theArgument.value) == 0.0 : FALSE))
00340 {
00341 DivideByZeroErrorMessage(theEnv,"/");
00342 SetHaltExecution(theEnv,TRUE);
00343 SetEvaluationError(theEnv,TRUE);
00344 returnValue->type = FLOAT;
00345 returnValue->value = (void *) EnvAddDouble(theEnv,1.0);
00346 return;
00347 }
00348
00349 if (useFloatTotal)
00350 { ftotal /= ValueToDouble(theArgument.value); }
00351 else
00352 {
00353 if (theArgument.type == INTEGER)
00354 { ltotal /= ValueToLong(theArgument.value); }
00355 else
00356 {
00357 ftotal = (double) ltotal / ValueToDouble(theArgument.value);
00358 useFloatTotal = TRUE;
00359 }
00360 }
00361 pos++;
00362 }
00363
00364
00365
00366
00367
00368
00369 if (useFloatTotal)
00370 {
00371 returnValue->type = FLOAT;
00372 returnValue->value = (void *) EnvAddDouble(theEnv,ftotal);
00373 }
00374 else
00375 {
00376 returnValue->type = INTEGER;
00377 returnValue->value = (void *) EnvAddLong(theEnv,ltotal);
00378 }
00379 }
00380
00381
00382
00383
00384
00385 globle long long DivFunction(
00386 void *theEnv)
00387 {
00388 long long total = 1LL;
00389 EXPRESSION *theExpression;
00390 DATA_OBJECT theArgument;
00391 int pos = 1;
00392 long long theNumber;
00393
00394
00395
00396
00397
00398
00399
00400 theExpression = GetFirstArgument();
00401 if (theExpression != NULL)
00402 {
00403 if (! GetNumericArgument(theEnv,theExpression,"div",&theArgument,FALSE,pos)) theExpression = NULL;
00404 else theExpression = GetNextArgument(theExpression);
00405
00406 if (theArgument.type == INTEGER)
00407 { total = ValueToLong(theArgument.value); }
00408 else
00409 { total = (long long) ValueToDouble(theArgument.value); }
00410 pos++;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420 while (theExpression != NULL)
00421 {
00422 if (! GetNumericArgument(theEnv,theExpression,"div",&theArgument,FALSE,pos)) theExpression = NULL;
00423 else theExpression = GetNextArgument(theExpression);
00424
00425 if (theArgument.type == INTEGER) theNumber = ValueToLong(theArgument.value);
00426 else if (theArgument.type == FLOAT) theNumber = (long long) ValueToDouble(theArgument.value);
00427 else theNumber = 1;
00428
00429 if (theNumber == 0LL)
00430 {
00431 DivideByZeroErrorMessage(theEnv,"div");
00432 SetHaltExecution(theEnv,TRUE);
00433 SetEvaluationError(theEnv,TRUE);
00434 return(1L);
00435 }
00436
00437 if (theArgument.type == INTEGER)
00438 { total /= ValueToLong(theArgument.value); }
00439 else
00440 { total = total / (long long) ValueToDouble(theArgument.value); }
00441
00442 pos++;
00443 }
00444
00445
00446
00447
00448
00449 return(total);
00450 }
00451
00452
00453
00454
00455
00456 globle int SetAutoFloatDividendCommand(
00457 void *theEnv)
00458 {
00459 int oldValue;
00460 DATA_OBJECT theArgument;
00461
00462
00463
00464
00465
00466 oldValue = BasicMathFunctionData(theEnv)->AutoFloatDividend;
00467
00468
00469
00470
00471
00472 if (EnvArgCountCheck(theEnv,"set-auto-float-dividend",EXACTLY,1) == -1)
00473 { return(oldValue); }
00474
00475 EnvRtnUnknown(theEnv,1,&theArgument);
00476
00477
00478
00479
00480
00481 if ((theArgument.value == EnvFalseSymbol(theEnv)) && (theArgument.type == SYMBOL))
00482 { BasicMathFunctionData(theEnv)->AutoFloatDividend = FALSE; }
00483 else
00484 { BasicMathFunctionData(theEnv)->AutoFloatDividend = TRUE; }
00485
00486
00487
00488
00489
00490 return(oldValue);
00491 }
00492
00493
00494
00495
00496
00497 globle int GetAutoFloatDividendCommand(
00498 void *theEnv)
00499 {
00500
00501
00502
00503
00504 EnvArgCountCheck(theEnv,"get-auto-float-dividend",EXACTLY,0);
00505
00506
00507
00508
00509
00510 return(BasicMathFunctionData(theEnv)->AutoFloatDividend);
00511 }
00512
00513
00514
00515
00516
00517 globle intBool EnvGetAutoFloatDividend(
00518 void *theEnv)
00519 {
00520 return(BasicMathFunctionData(theEnv)->AutoFloatDividend);
00521 }
00522
00523
00524
00525
00526
00527 globle intBool EnvSetAutoFloatDividend(
00528 void *theEnv,
00529 int value)
00530 {
00531 int ov;
00532
00533 ov = BasicMathFunctionData(theEnv)->AutoFloatDividend;
00534 BasicMathFunctionData(theEnv)->AutoFloatDividend = value;
00535 return(ov);
00536 }
00537
00538
00539
00540
00541
00542 globle long long IntegerFunction(
00543 void *theEnv)
00544 {
00545 DATA_OBJECT valstruct;
00546
00547
00548
00549
00550
00551 if (EnvArgCountCheck(theEnv,"integer",EXACTLY,1) == -1) return(0LL);
00552
00553
00554
00555
00556
00557
00558
00559 if (EnvArgTypeCheck(theEnv,"integer",1,INTEGER,&valstruct) == FALSE) return(0LL);
00560
00561
00562
00563
00564
00565 return(ValueToLong(valstruct.value));
00566 }
00567
00568
00569
00570
00571
00572 globle double FloatFunction(
00573 void *theEnv)
00574 {
00575 DATA_OBJECT valstruct;
00576
00577
00578
00579
00580
00581 if (EnvArgCountCheck(theEnv,"float",EXACTLY,1) == -1) return(0.0);
00582
00583
00584
00585
00586
00587
00588
00589 if (EnvArgTypeCheck(theEnv,"float",1,FLOAT,&valstruct) == FALSE) return(0.0);
00590
00591
00592
00593
00594
00595 return(ValueToDouble(valstruct.value));
00596 }
00597
00598
00599
00600
00601
00602 globle void AbsFunction(
00603 void *theEnv,
00604 DATA_OBJECT_PTR returnValue)
00605 {
00606
00607
00608
00609
00610 if (EnvArgCountCheck(theEnv,"abs",EXACTLY,1) == -1)
00611 {
00612 returnValue->type = INTEGER;
00613 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00614 return;
00615 }
00616
00617
00618
00619
00620
00621 if (EnvArgTypeCheck(theEnv,"abs",1,INTEGER_OR_FLOAT,returnValue) == FALSE)
00622 {
00623 returnValue->type = INTEGER;
00624 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00625 return;
00626 }
00627
00628
00629
00630
00631
00632 if (returnValue->type == INTEGER)
00633 {
00634 if (ValueToLong(returnValue->value) < 0L)
00635 { returnValue->value = (void *) EnvAddLong(theEnv,- ValueToLong(returnValue->value)); }
00636 }
00637 else if (ValueToDouble(returnValue->value) < 0.0)
00638 { returnValue->value = (void *) EnvAddDouble(theEnv,- ValueToDouble(returnValue->value)); }
00639 }
00640
00641
00642
00643
00644
00645 globle void MinFunction(
00646 void *theEnv,
00647 DATA_OBJECT_PTR returnValue)
00648 {
00649 DATA_OBJECT argValue;
00650 int numberOfArguments, i;
00651
00652
00653
00654
00655
00656 if ((numberOfArguments = EnvArgCountCheck(theEnv,"min",AT_LEAST,1)) == -1)
00657 {
00658 returnValue->type = INTEGER;
00659 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00660 return;
00661 }
00662
00663
00664
00665
00666
00667 if (EnvArgTypeCheck(theEnv,"min",1,INTEGER_OR_FLOAT,returnValue) == FALSE)
00668 {
00669 returnValue->type = INTEGER;
00670 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00671 return;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681 for (i = 2 ; i <= numberOfArguments ; i++)
00682 {
00683 if (EnvArgTypeCheck(theEnv,"min",i,INTEGER_OR_FLOAT,&argValue) == FALSE) return;
00684
00685 if (returnValue->type == INTEGER)
00686 {
00687 if (argValue.type == INTEGER)
00688 {
00689 if (ValueToLong(returnValue->value) > ValueToLong(argValue.value))
00690 {
00691 returnValue->type = argValue.type;
00692 returnValue->value = argValue.value;
00693 }
00694 }
00695 else
00696 {
00697 if ((double) ValueToLong(returnValue->value) >
00698 ValueToDouble(argValue.value))
00699 {
00700 returnValue->type = argValue.type;
00701 returnValue->value = argValue.value;
00702 }
00703 }
00704 }
00705 else
00706 {
00707 if (argValue.type == INTEGER)
00708 {
00709 if (ValueToDouble(returnValue->value) >
00710 (double) ValueToLong(argValue.value))
00711 {
00712 returnValue->type = argValue.type;
00713 returnValue->value = argValue.value;
00714 }
00715 }
00716 else
00717 {
00718 if (ValueToDouble(returnValue->value) > ValueToDouble(argValue.value))
00719 {
00720 returnValue->type = argValue.type;
00721 returnValue->value = argValue.value;
00722 }
00723 }
00724 }
00725 }
00726
00727 return;
00728 }
00729
00730
00731
00732
00733
00734 globle void MaxFunction(
00735 void *theEnv,
00736 DATA_OBJECT_PTR returnValue)
00737 {
00738 DATA_OBJECT argValue;
00739 int numberOfArguments, i;
00740
00741
00742
00743
00744
00745 if ((numberOfArguments = EnvArgCountCheck(theEnv,"max",AT_LEAST,1)) == -1)
00746 {
00747 returnValue->type = INTEGER;
00748 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00749 return;
00750 }
00751
00752
00753
00754
00755
00756 if (EnvArgTypeCheck(theEnv,"max",1,INTEGER_OR_FLOAT,returnValue) == FALSE)
00757 {
00758 returnValue->type = INTEGER;
00759 returnValue->value = (void *) EnvAddLong(theEnv,0L);
00760 return;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770 for (i = 2 ; i <= numberOfArguments ; i++)
00771 {
00772 if (EnvArgTypeCheck(theEnv,"max",i,INTEGER_OR_FLOAT,&argValue) == FALSE) return;
00773
00774 if (returnValue->type == INTEGER)
00775 {
00776 if (argValue.type == INTEGER)
00777 {
00778 if (ValueToLong(returnValue->value) < ValueToLong(argValue.value))
00779 {
00780 returnValue->type = argValue.type;
00781 returnValue->value = argValue.value;
00782 }
00783 }
00784 else
00785 {
00786 if ((double) ValueToLong(returnValue->value) <
00787 ValueToDouble(argValue.value))
00788 {
00789 returnValue->type = argValue.type;
00790 returnValue->value = argValue.value;
00791 }
00792 }
00793 }
00794 else
00795 {
00796 if (argValue.type == INTEGER)
00797 {
00798 if (ValueToDouble(returnValue->value) <
00799 (double) ValueToLong(argValue.value))
00800 {
00801 returnValue->type = argValue.type;
00802 returnValue->value = argValue.value;
00803 }
00804 }
00805 else
00806 {
00807 if (ValueToDouble(returnValue->value) < ValueToDouble(argValue.value))
00808 {
00809 returnValue->type = argValue.type;
00810 returnValue->value = argValue.value;
00811 }
00812 }
00813 }
00814 }
00815
00816 return;
00817 }
00818