mux/src/funmath.cpp

Go to the documentation of this file.
00001 // funmath.cpp -- MUX math function handlers.
00002 //
00003 // $Id: funmath.cpp,v 1.8 2007/04/07 17:19:30 sdennis Exp $
00004 //
00005 // MUX 2.4
00006 // Copyright (C) 1998 through 2005 Solid Vertical Domains, Ltd. All
00007 // rights not explicitly given are reserved.
00008 //
00009 #include "copyright.h"
00010 #include "autoconf.h"
00011 #include "config.h"
00012 #include "externs.h"
00013 
00014 #include <float.h>
00015 #include <limits.h>
00016 #include <math.h>
00017 
00018 #include "functions.h"
00019 #include "funmath.h"
00020 #include "sha1.h"
00021 
00022 #ifdef HAVE_IEEE_FP_FORMAT
00023 
00024 static const char *mux_FPStrings[] = { "+Inf", "-Inf", "Ind", "NaN", "0", "0", "0", "0" };
00025 
00026 #define MUX_FPGROUP_PASS  0x00 // Pass-through to printf
00027 #define MUX_FPGROUP_ZERO  0x10 // Force to be zero.
00028 #define MUX_FPGROUP_PINF  0x20 // "+Inf"
00029 #define MUX_FPGROUP_NINF  0x30 // "-Inf"
00030 #define MUX_FPGROUP_IND   0x40 // "Ind"
00031 #define MUX_FPGROUP_NAN   0x50 // "NaN"
00032 #define MUX_FPGROUP(x) ((x) & 0xF0)
00033 
00034 // mux_fpclass returns an integer that is one of the following:
00035 //
00036 #define MUX_FPCLASS_PINF  (MUX_FPGROUP_PINF|0) // Positive infinity (+INF)
00037 #define MUX_FPCLASS_NINF  (MUX_FPGROUP_NINF|1) // Negative infinity (-INF)
00038 #define MUX_FPCLASS_QNAN  (MUX_FPGROUP_IND |2) // Quiet NAN (Indefinite)
00039 #define MUX_FPCLASS_SNAN  (MUX_FPGROUP_NAN |3) // Signaling NAN
00040 #define MUX_FPCLASS_ND    (MUX_FPGROUP_ZERO|4) // Negative denormalized
00041 #define MUX_FPCLASS_NZ    (MUX_FPGROUP_ZERO|5) // Negative zero (-0)
00042 #define MUX_FPCLASS_PZ    (MUX_FPGROUP_ZERO|6) // Positive zero (+0)
00043 #define MUX_FPCLASS_PD    (MUX_FPGROUP_ZERO|7) // Positive denormalized
00044 #define MUX_FPCLASS_PN    (MUX_FPGROUP_PASS|8) // Positive normalized non-zero
00045 #define MUX_FPCLASS_NN    (MUX_FPGROUP_PASS|9) // Negative normalized non-zero
00046 #define MUX_FPCLASS(x)    ((x) & 0x0F)
00047 
00048 #ifdef WIN32
00049 #define IEEE_MASK_SIGN     0x8000000000000000ui64
00050 #define IEEE_MASK_EXPONENT 0x7FF0000000000000ui64
00051 #define IEEE_MASK_MANTISSA 0x000FFFFFFFFFFFFFui64
00052 #define IEEE_MASK_QNAN     0x0008000000000000ui64
00053 #else
00054 #define IEEE_MASK_SIGN     0x8000000000000000ull
00055 #define IEEE_MASK_EXPONENT 0x7FF0000000000000ull
00056 #define IEEE_MASK_MANTISSA 0x000FFFFFFFFFFFFFull
00057 #define IEEE_MASK_QNAN     0x0008000000000000ull
00058 #endif
00059 
00060 #define ARBITRARY_NUMBER 1
00061 #define IEEE_MAKE_TABLESIZE 5
00062 typedef union
00063 {
00064     INT64  i64;
00065     double d;
00066 } SpecialFloatUnion;
00067 
00068 // We return a Quiet NAN when a Signalling NAN is requested because
00069 // any operation on a Signalling NAN will result in a Quiet NAN anyway.
00070 // MUX doesn't catch SIGFPE, but if it did, a Signalling NAN would
00071 // generate a SIGFPE.
00072 //
00073 static SpecialFloatUnion SpecialFloatTable[IEEE_MAKE_TABLESIZE] =
00074 {
00075     { 0 }, // Unused.
00076     { IEEE_MASK_EXPONENT | IEEE_MASK_QNAN | ARBITRARY_NUMBER },
00077     { IEEE_MASK_EXPONENT | IEEE_MASK_QNAN | ARBITRARY_NUMBER },
00078     { IEEE_MASK_EXPONENT },
00079     { IEEE_MASK_EXPONENT | IEEE_MASK_SIGN }
00080 };
00081 
00082 double MakeSpecialFloat(int iWhich)
00083 {
00084     return SpecialFloatTable[iWhich].d;
00085 }
00086 
00087 static int mux_fpclass(double result)
00088 {
00089     union
00090     {
00091         UINT64 i64;
00092         double d;
00093     } u;
00094 
00095     u.d = result;
00096   
00097     if ((u.i64 & IEEE_MASK_EXPONENT) == 0)
00098     {
00099         if (u.i64 & IEEE_MASK_MANTISSA)
00100         {
00101             if (u.i64 & IEEE_MASK_SIGN) return MUX_FPCLASS_ND;
00102             else                        return MUX_FPCLASS_PD;
00103         }
00104         else
00105         {
00106             if (u.i64 & IEEE_MASK_SIGN) return MUX_FPCLASS_NZ;
00107             else                        return MUX_FPCLASS_PZ;
00108         }
00109     }
00110     else if ((u.i64 & IEEE_MASK_EXPONENT) == IEEE_MASK_EXPONENT)
00111     {
00112         if (u.i64 & IEEE_MASK_MANTISSA)
00113         {
00114             if (u.i64 & IEEE_MASK_QNAN) return MUX_FPCLASS_QNAN;
00115             else                        return MUX_FPCLASS_SNAN;
00116         }
00117         else
00118         {
00119             if (u.i64 & IEEE_MASK_SIGN) return MUX_FPCLASS_NINF;
00120             else                        return MUX_FPCLASS_PINF;
00121         }
00122     }
00123     else
00124     {
00125         if (u.i64 & IEEE_MASK_SIGN)     return MUX_FPCLASS_NN;
00126         else                            return MUX_FPCLASS_PN;
00127     }
00128 }
00129 #endif // HAVE_IEEE_FP_FORMAT
00130 
00131 static double AddWithError(double& err, double a, double b)
00132 {
00133     double sum = a+b;
00134     err = b-(sum-a);
00135     return sum;
00136 }
00137 
00138 // Typically, we are within 1ulp of an exact answer, find the shortest answer
00139 // within that 1 ulp (that is, within 0, +ulp, and -ulp).
00140 //
00141 static double NearestPretty(double R)
00142 {
00143     char *rve = NULL;
00144     int decpt;
00145     int bNegative;
00146     const int mode = 0;
00147 
00148     double ulpR = ulp(R);
00149     double R0 = R-ulpR;
00150     double R1 = R+ulpR;
00151 
00152     // R.
00153     //
00154     char *p = mux_dtoa(R, mode, 50, &decpt, &bNegative, &rve);
00155     int nDigits = rve - p;
00156 
00157     // R-ulp(R)
00158     //
00159     p = mux_dtoa(R0, mode, 50, &decpt, &bNegative, &rve);
00160     if (rve - p < nDigits)
00161     {
00162         nDigits = rve - p;
00163         R  = R0;
00164     }
00165 
00166     // R+ulp(R)
00167     //
00168     p = mux_dtoa(R1, mode, 50, &decpt, &bNegative, &rve);
00169     if (rve - p < nDigits)
00170     {
00171         nDigits = rve - p;
00172         R = R1;
00173     }
00174     return R;
00175 }
00176 
00177 // Compare for decreasing order by absolute value.
00178 //
00179 static int DCL_CDECL f_comp_abs(const void *s1, const void *s2)
00180 {
00181     double a = fabs(*(double *)s1);
00182     double b = fabs(*(double *)s2);
00183 
00184     if (a > b)
00185     {
00186         return -1;
00187     }
00188     else if (a < b)
00189     {
00190         return 1;
00191     }
00192     return 0;
00193 }
00194 
00195 // Double compensation method. Extended by Priest from Knuth and Kahan.
00196 //
00197 // Error of sum is less than 2*epsilon or 1 ulp except for very large n.
00198 // Return the result that yields the shortest number of base-10 digits.
00199 //
00200 static double AddDoubles(int n, double pd[])
00201 {
00202     qsort(pd, n, sizeof(double), f_comp_abs);
00203     double sum = 0.0;
00204     if (0 < n)
00205     {
00206         sum = pd[0];
00207         double sum_err = 0.0;
00208         int i;
00209         for (i = 1; i < n; i++)
00210         {
00211             double addend_err;
00212             double addend = AddWithError(addend_err, sum_err, pd[i]);
00213             double sum1_err;
00214             double sum1 = AddWithError(sum1_err, sum, addend);
00215             sum = AddWithError(sum_err, sum1, addend_err + sum1_err);
00216         }
00217     }
00218     return NearestPretty(sum);
00219 }
00220 
00221 /* ---------------------------------------------------------------------------
00222  * fval: copy the floating point value into a buffer and make it presentable
00223  */
00224 static void fval(char *buff, char **bufc, double result)
00225 {
00226     // Get double val into buffer.
00227     //
00228 #ifdef HAVE_IEEE_FP_FORMAT
00229     int fpc = mux_fpclass(result);
00230     if (MUX_FPGROUP(fpc) == MUX_FPGROUP_PASS)
00231     {
00232 #endif // HAVE_IEEE_FP_FORMAT
00233         double rIntegerPart;
00234         double rFractionalPart = modf(result, &rIntegerPart);
00235         if (  0.0 == rFractionalPart
00236            && LONG_MIN <= rIntegerPart
00237            && rIntegerPart <= LONG_MAX)
00238         {
00239             long i = (long)rIntegerPart;
00240             safe_ltoa(i, buff, bufc);
00241         }
00242         else
00243         {
00244             safe_str(mux_ftoa(result, false, 0), buff, bufc);
00245         }
00246 #ifdef HAVE_IEEE_FP_FORMAT
00247     }
00248     else
00249     {
00250         safe_str(mux_FPStrings[MUX_FPCLASS(fpc)], buff, bufc);
00251     }
00252 #endif // HAVE_IEEE_FP_FORMAT
00253 }
00254 
00255 static const long nMaximums[10] =
00256 {
00257     0, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999
00258 };
00259 
00260 static double g_aDoubles[LBUF_SIZE];
00261 int const g_nDoubles = sizeof(g_aDoubles)/sizeof(double);
00262 
00263 FUNCTION(fun_add)
00264 {
00265     UNUSED_PARAMETER(executor);
00266     UNUSED_PARAMETER(caller);
00267     UNUSED_PARAMETER(enactor);
00268     UNUSED_PARAMETER(cargs);
00269     UNUSED_PARAMETER(ncargs);
00270 
00271     int nArgs = nfargs;
00272     if (g_nDoubles < nArgs)
00273     {
00274         nArgs = g_nDoubles;
00275     }
00276 
00277     int i;
00278     for (i = 0; i < nArgs; i++)
00279     {
00280         int nDigits;
00281         long nMaxValue = 0;
00282         if (  !is_integer(fargs[i], &nDigits)
00283            || nDigits > 9
00284            || (nMaxValue += nMaximums[nDigits]) > 999999999L)
00285         {
00286             // Do it the slow way.
00287             //
00288             for (int j = 0; j < nArgs; j++)
00289             {
00290                 g_aDoubles[j] = mux_atof(fargs[j]);
00291             }
00292 
00293             fval(buff, bufc, AddDoubles(nArgs, g_aDoubles));
00294             return;
00295         }
00296     }
00297 
00298     // We can do it the fast way.
00299     //
00300     long sum = 0;
00301     for (i = 0; i < nArgs; i++)
00302     {
00303         sum += mux_atol(fargs[i]);
00304     }
00305     safe_ltoa(sum, buff, bufc);
00306 }
00307 
00308 FUNCTION(fun_ladd)
00309 {
00310     UNUSED_PARAMETER(executor);
00311     UNUSED_PARAMETER(caller);
00312     UNUSED_PARAMETER(enactor);
00313     UNUSED_PARAMETER(cargs);
00314     UNUSED_PARAMETER(ncargs);
00315 
00316     int n = 0;
00317     if (0 < nfargs)
00318     {
00319         SEP sep;
00320         if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
00321         {
00322             return;
00323         }
00324 
00325         char *cp = trim_space_sep(fargs[0], &sep);
00326         while (  cp
00327               && n < g_nDoubles)
00328         {
00329             char *curr = split_token(&cp, &sep);
00330             g_aDoubles[n++] = mux_atof(curr);
00331         }
00332     }
00333     fval(buff, bufc, AddDoubles(n, g_aDoubles));
00334 }
00335 
00337 // Function : iadd(Arg[0], Arg[1],..,Arg[n])
00338 //
00339 // Written by : Chris Rouse (Seraphim) 04/04/2000
00341 
00342 FUNCTION(fun_iadd)
00343 {
00344     UNUSED_PARAMETER(executor);
00345     UNUSED_PARAMETER(caller);
00346     UNUSED_PARAMETER(enactor);
00347     UNUSED_PARAMETER(cargs);
00348     UNUSED_PARAMETER(ncargs);
00349 
00350     INT64 sum = 0;
00351     for (int i = 0; i < nfargs; i++)
00352     {
00353         sum += mux_atoi64(fargs[i]);
00354     }
00355     safe_i64toa(sum, buff, bufc);
00356 }
00357 
00358 FUNCTION(fun_sub)
00359 {
00360     UNUSED_PARAMETER(executor);
00361     UNUSED_PARAMETER(caller);
00362     UNUSED_PARAMETER(enactor);
00363     UNUSED_PARAMETER(nfargs);
00364     UNUSED_PARAMETER(cargs);
00365     UNUSED_PARAMETER(ncargs);
00366 
00367     int nDigits;
00368     if (  is_integer(fargs[0], &nDigits)
00369        && nDigits <= 9
00370        && is_integer(fargs[1], &nDigits)
00371        && nDigits <= 9)
00372     {
00373         int iResult;
00374         iResult = mux_atol(fargs[0]) - mux_atol(fargs[1]);
00375         safe_ltoa(iResult, buff, bufc);
00376     }
00377     else
00378     {
00379         g_aDoubles[0] = mux_atof(fargs[0]);
00380         g_aDoubles[1] = -mux_atof(fargs[1]);
00381         fval(buff, bufc, AddDoubles(2, g_aDoubles));
00382     }
00383 }
00384 
00386 // Function : isub(Arg[0], Arg[1])
00387 //
00388 // Written by : Chris Rouse (Seraphim) 04/04/2000
00390 
00391 FUNCTION(fun_isub)
00392 {
00393     UNUSED_PARAMETER(executor);
00394     UNUSED_PARAMETER(caller);
00395     UNUSED_PARAMETER(enactor);
00396     UNUSED_PARAMETER(nfargs);
00397     UNUSED_PARAMETER(cargs);
00398     UNUSED_PARAMETER(ncargs);
00399 
00400     INT64 diff = mux_atoi64(fargs[0]) - mux_atoi64(fargs[1]);
00401     safe_i64toa(diff, buff, bufc);
00402 }
00403 
00404 FUNCTION(fun_mul)
00405 {
00406     UNUSED_PARAMETER(executor);
00407     UNUSED_PARAMETER(caller);
00408     UNUSED_PARAMETER(enactor);
00409     UNUSED_PARAMETER(cargs);
00410     UNUSED_PARAMETER(ncargs);
00411 
00412     double prod = 1.0;
00413     for (int i = 0; i < nfargs; i++)
00414     {
00415         prod *= mux_atof(fargs[i]);
00416     }
00417     fval(buff, bufc, NearestPretty(prod));
00418 }
00419 
00421 // Function : imul(Arg[0], Arg[1], ... , Arg[n])
00422 //
00423 // Written by : Chris Rouse (Seraphim) 04/04/2000
00425 
00426 FUNCTION(fun_imul)
00427 {
00428     UNUSED_PARAMETER(executor);
00429     UNUSED_PARAMETER(caller);
00430     UNUSED_PARAMETER(enactor);
00431     UNUSED_PARAMETER(cargs);
00432     UNUSED_PARAMETER(ncargs);
00433 
00434     INT64 prod = 1;
00435     for (int i = 0; i < nfargs; i++)
00436     {
00437         prod *= mux_atoi64(fargs[i]);
00438     }
00439     safe_i64toa(prod, buff, bufc);
00440 }
00441 
00442 FUNCTION(fun_gt)
00443 {
00444     UNUSED_PARAMETER(executor);
00445     UNUSED_PARAMETER(caller);
00446     UNUSED_PARAMETER(enactor);
00447     UNUSED_PARAMETER(nfargs);
00448     UNUSED_PARAMETER(cargs);
00449     UNUSED_PARAMETER(ncargs);
00450 
00451     bool bResult = false;
00452     int nDigits;
00453     if (  is_integer(fargs[0], &nDigits)
00454        && nDigits <= 9
00455        && is_integer(fargs[1], &nDigits)
00456        && nDigits <= 9)
00457     {
00458         bResult = (mux_atol(fargs[0]) > mux_atol(fargs[1]));
00459     }
00460     else
00461     {
00462         bResult = (mux_atof(fargs[0]) > mux_atof(fargs[1]));
00463     }
00464     safe_bool(bResult, buff, bufc);
00465 }
00466 
00467 FUNCTION(fun_gte)
00468 {
00469     UNUSED_PARAMETER(executor);
00470     UNUSED_PARAMETER(caller);
00471     UNUSED_PARAMETER(enactor);
00472     UNUSED_PARAMETER(nfargs);
00473     UNUSED_PARAMETER(cargs);
00474     UNUSED_PARAMETER(ncargs);
00475 
00476     bool bResult = false;
00477     int nDigits;
00478     if (  is_integer(fargs[0], &nDigits)
00479        && nDigits <= 9
00480        && is_integer(fargs[1], &nDigits)
00481        && nDigits <= 9)
00482     {
00483         bResult = (mux_atol(fargs[0]) >= mux_atol(fargs[1]));
00484     }
00485     else
00486     {
00487         bResult = (mux_atof(fargs[0]) >= mux_atof(fargs[1]));
00488     }
00489     safe_bool(bResult, buff, bufc);
00490 }
00491 
00492 FUNCTION(fun_lt)
00493 {
00494     UNUSED_PARAMETER(executor);
00495     UNUSED_PARAMETER(caller);
00496     UNUSED_PARAMETER(enactor);
00497     UNUSED_PARAMETER(nfargs);
00498     UNUSED_PARAMETER(cargs);
00499     UNUSED_PARAMETER(ncargs);
00500 
00501     bool bResult = false;
00502     int nDigits;
00503     if (  is_integer(fargs[0], &nDigits)
00504        && nDigits <= 9
00505        && is_integer(fargs[1], &nDigits)
00506        && nDigits <= 9)
00507     {
00508         bResult = (mux_atol(fargs[0]) < mux_atol(fargs[1]));
00509     }
00510     else
00511     {
00512         bResult = (mux_atof(fargs[0]) < mux_atof(fargs[1]));
00513     }
00514     safe_bool(bResult, buff, bufc);
00515 }
00516 
00517 FUNCTION(fun_lte)
00518 {
00519     UNUSED_PARAMETER(executor);
00520     UNUSED_PARAMETER(caller);
00521     UNUSED_PARAMETER(enactor);
00522     UNUSED_PARAMETER(nfargs);
00523     UNUSED_PARAMETER(cargs);
00524     UNUSED_PARAMETER(ncargs);
00525 
00526     bool bResult = false;
00527     int nDigits;
00528     if (  is_integer(fargs[0], &nDigits)
00529        && nDigits <= 9
00530        && is_integer(fargs[1], &nDigits)
00531        && nDigits <= 9)
00532     {
00533         bResult = (mux_atol(fargs[0]) <= mux_atol(fargs[1]));
00534     }
00535     else
00536     {
00537         bResult = (mux_atof(fargs[0]) <= mux_atof(fargs[1]));
00538     }
00539     safe_bool(bResult, buff, bufc);
00540 }
00541 
00542 FUNCTION(fun_eq)
00543 {
00544     UNUSED_PARAMETER(executor);
00545     UNUSED_PARAMETER(caller);
00546     UNUSED_PARAMETER(enactor);
00547     UNUSED_PARAMETER(nfargs);
00548     UNUSED_PARAMETER(cargs);
00549     UNUSED_PARAMETER(ncargs);
00550 
00551     bool bResult = false;
00552     int nDigits;
00553     if (  is_integer(fargs[0], &nDigits)
00554        && nDigits <= 9
00555        && is_integer(fargs[1], &nDigits)
00556        && nDigits <= 9)
00557     {
00558         bResult = (mux_atol(fargs[0]) == mux_atol(fargs[1]));
00559     }
00560     else
00561     {
00562         bResult = (  strcmp(fargs[0], fargs[1]) == 0
00563                   || mux_atof(fargs[0]) == mux_atof(fargs[1]));
00564     }
00565     safe_bool(bResult, buff, bufc);
00566 }
00567 
00568 FUNCTION(fun_neq)
00569 {
00570     UNUSED_PARAMETER(executor);
00571     UNUSED_PARAMETER(caller);
00572     UNUSED_PARAMETER(enactor);
00573     UNUSED_PARAMETER(nfargs);
00574     UNUSED_PARAMETER(cargs);
00575     UNUSED_PARAMETER(ncargs);
00576 
00577     bool bResult = false;
00578     int nDigits;
00579     if (  is_integer(fargs[0], &nDigits)
00580        && nDigits <= 9
00581        && is_integer(fargs[1], &nDigits)
00582        && nDigits <= 9)
00583     {
00584         bResult = (mux_atol(fargs[0]) != mux_atol(fargs[1]));
00585     }
00586     else
00587     {
00588         bResult = (  strcmp(fargs[0], fargs[1]) != 0
00589                   && mux_atof(fargs[0]) != mux_atof(fargs[1]));
00590     }
00591     safe_bool(bResult, buff, bufc);
00592 }
00593 
00594 /*
00595  * ---------------------------------------------------------------------------
00596  * * fun_max, fun_min: Return maximum (minimum) value.
00597  */
00598 
00599 FUNCTION(fun_max)
00600 {
00601     UNUSED_PARAMETER(executor);
00602     UNUSED_PARAMETER(caller);
00603     UNUSED_PARAMETER(enactor);
00604     UNUSED_PARAMETER(cargs);
00605     UNUSED_PARAMETER(ncargs);
00606 
00607     double maximum = 0.0;
00608     for (int i = 0; i < nfargs; i++)
00609     {
00610         double tval = mux_atof(fargs[i]);
00611         if (  i == 0
00612            || tval > maximum)
00613         {
00614             maximum = tval;
00615         }
00616     }
00617     fval(buff, bufc, maximum);
00618 }
00619 
00620 FUNCTION(fun_min)
00621 {
00622     UNUSED_PARAMETER(executor);
00623     UNUSED_PARAMETER(caller);
00624     UNUSED_PARAMETER(enactor);
00625     UNUSED_PARAMETER(cargs);
00626     UNUSED_PARAMETER(ncargs);
00627 
00628     double minimum = 0.0;
00629     for (int i = 0; i < nfargs; i++)
00630     {
00631         double tval = mux_atof(fargs[i]);
00632         if (  i == 0
00633            || tval < minimum)
00634         {
00635             minimum = tval;
00636         }
00637     }
00638     fval(buff, bufc, minimum);
00639 }
00640 
00641 /* ---------------------------------------------------------------------------
00642  * fun_sign: Returns -1, 0, or 1 based on the the sign of its argument.
00643  */
00644 
00645 FUNCTION(fun_sign)
00646 {
00647     UNUSED_PARAMETER(executor);
00648     UNUSED_PARAMETER(caller);
00649     UNUSED_PARAMETER(enactor);
00650     UNUSED_PARAMETER(nfargs);
00651     UNUSED_PARAMETER(cargs);
00652     UNUSED_PARAMETER(ncargs);
00653 
00654     double num = mux_atof(fargs[0]);
00655     if (num < 0)
00656     {
00657         safe_str("-1", buff, bufc);
00658     }
00659     else
00660     {
00661         safe_bool(num > 0, buff, bufc);
00662     }
00663 }
00664 
00665 // fun_isign: Returns -1, 0, or 1 based on the the sign of its argument.
00666 //
00667 FUNCTION(fun_isign)
00668 {
00669     UNUSED_PARAMETER(executor);
00670     UNUSED_PARAMETER(caller);
00671     UNUSED_PARAMETER(enactor);
00672     UNUSED_PARAMETER(nfargs);
00673     UNUSED_PARAMETER(cargs);
00674     UNUSED_PARAMETER(ncargs);
00675 
00676     INT64 num = mux_atoi64(fargs[0]);
00677 
00678     if (num < 0)
00679     {
00680         safe_str("-1", buff, bufc);
00681     }
00682     else
00683     {
00684         safe_bool(num > 0, buff, bufc);
00685     }
00686 }
00687 
00688 // shl() and shr() borrowed from PennMUSH 1.50
00689 //
00690 FUNCTION(fun_shl)
00691 {
00692     UNUSED_PARAMETER(executor);
00693     UNUSED_PARAMETER(caller);
00694     UNUSED_PARAMETER(enactor);
00695     UNUSED_PARAMETER(nfargs);
00696     UNUSED_PARAMETER(cargs);
00697     UNUSED_PARAMETER(ncargs);
00698 
00699     if (  is_integer(fargs[0], NULL)
00700        && is_integer(fargs[1], NULL))
00701     {
00702         INT64 a = mux_atoi64(fargs[0]);
00703         long  b = mux_atol(fargs[1]);
00704         safe_i64toa(a << b, buff, bufc);
00705     }
00706     else
00707     {
00708         safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
00709     }
00710 }
00711 
00712 FUNCTION(fun_shr)
00713 {
00714     UNUSED_PARAMETER(executor);
00715     UNUSED_PARAMETER(caller);
00716     UNUSED_PARAMETER(enactor);
00717     UNUSED_PARAMETER(nfargs);
00718     UNUSED_PARAMETER(cargs);
00719     UNUSED_PARAMETER(ncargs);
00720 
00721     if (  is_integer(fargs[0], NULL)
00722        && is_integer(fargs[1], NULL))
00723     {
00724         INT64 a = mux_atoi64(fargs[0]);
00725         long  b = mux_atol(fargs[1]);
00726         safe_i64toa(a >> b, buff, bufc);
00727     }
00728     else
00729     {
00730         safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
00731     }
00732 }
00733 
00734 FUNCTION(fun_inc)
00735 {
00736     UNUSED_PARAMETER(executor);
00737     UNUSED_PARAMETER(caller);
00738     UNUSED_PARAMETER(enactor);
00739     UNUSED_PARAMETER(cargs);
00740     UNUSED_PARAMETER(ncargs);
00741 
00742     if (nfargs == 1)
00743     {
00744         safe_i64toa(mux_atoi64(fargs[0]) + 1, buff, bufc);
00745     }
00746     else
00747     {
00748         safe_chr('1', buff, bufc);
00749     }
00750 }
00751 
00752 FUNCTION(fun_dec)
00753 {
00754     UNUSED_PARAMETER(executor);
00755     UNUSED_PARAMETER(caller);
00756     UNUSED_PARAMETER(enactor);
00757     UNUSED_PARAMETER(cargs);
00758     UNUSED_PARAMETER(ncargs);
00759 
00760     if (nfargs == 1)
00761     {
00762         safe_i64toa(mux_atoi64(fargs[0]) - 1, buff, bufc);
00763     }
00764     else
00765     {
00766         safe_str("-1", buff, bufc);
00767     }
00768 }
00769 
00770 FUNCTION(fun_trunc)
00771 {
00772     UNUSED_PARAMETER(executor);
00773     UNUSED_PARAMETER(caller);
00774     UNUSED_PARAMETER(enactor);
00775     UNUSED_PARAMETER(nfargs);
00776     UNUSED_PARAMETER(cargs);
00777     UNUSED_PARAMETER(ncargs);
00778 
00779     double rArg = mux_atof(fargs[0]);
00780     double rIntegerPart;
00781 
00782     mux_FPRestore();
00783     (void)modf(rArg, &rIntegerPart);
00784     mux_FPSet();
00785 
00786 #ifdef HAVE_IEEE_FP_FORMAT
00787     int fpc = mux_fpclass(rIntegerPart);
00788     if (MUX_FPGROUP(fpc) == MUX_FPGROUP_PASS)
00789     {
00790 #endif // HAVE_IEEE_FP_FORMAT
00791         safe_tprintf_str(buff, bufc, "%.0f", rIntegerPart);
00792 #ifdef HAVE_IEEE_FP_FORMAT
00793     }
00794     else
00795     {
00796         safe_str(mux_FPStrings[MUX_FPCLASS(fpc)], buff, bufc);
00797     }
00798 #endif // HAVE_IEEE_FP_FORMAT
00799 }
00800 
00801 FUNCTION(fun_fdiv)
00802 {
00803     UNUSED_PARAMETER(executor);
00804     UNUSED_PARAMETER(caller);
00805     UNUSED_PARAMETER(enactor);
00806     UNUSED_PARAMETER(nfargs);
00807     UNUSED_PARAMETER(cargs);
00808     UNUSED_PARAMETER(ncargs);
00809 
00810     double bot = mux_atof(fargs[1]);
00811     double top = mux_atof(fargs[0]);
00812 #ifndef HAVE_IEEE_FP_SNAN
00813     if (bot == 0.0)
00814     {
00815         if (top > 0.0)
00816         {
00817             safe_str("+Inf", buff, bufc);
00818         }
00819         else if (top < 0.0)
00820         {
00821             safe_str("-Inf", buff, bufc);
00822         }
00823         else
00824         {
00825             safe_str("Ind", buff, bufc);
00826         }
00827     }
00828     else
00829     {
00830         fval(buff, bufc, top/bot);
00831     }
00832 #else
00833     fval(buff, bufc, top/bot);
00834 #endif
00835 }
00836 
00837 FUNCTION(fun_idiv)
00838 {
00839     UNUSED_PARAMETER(executor);
00840     UNUSED_PARAMETER(caller);
00841     UNUSED_PARAMETER(enactor);
00842     UNUSED_PARAMETER(nfargs);
00843     UNUSED_PARAMETER(cargs);
00844     UNUSED_PARAMETER(ncargs);
00845 
00846     INT64 bot, top;
00847 
00848     bot = mux_atoi64(fargs[1]);
00849     if (bot == 0)
00850     {
00851         safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
00852     }
00853     else
00854     {
00855         top = mux_atoi64(fargs[0]);
00856         top = i64Division(top, bot);
00857         safe_i64toa(top, buff, bufc);
00858     }
00859 }
00860 
00861 FUNCTION(fun_floordiv)
00862 {
00863     UNUSED_PARAMETER(executor);
00864     UNUSED_PARAMETER(caller);
00865     UNUSED_PARAMETER(enactor);
00866     UNUSED_PARAMETER(nfargs);
00867     UNUSED_PARAMETER(cargs);
00868     UNUSED_PARAMETER(ncargs);
00869 
00870     INT64 bot, top;
00871 
00872     bot = mux_atoi64(fargs[1]);
00873     if (bot == 0)
00874     {
00875         safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
00876     }
00877     else
00878     {
00879         top = mux_atoi64(fargs[0]);
00880         top = i64FloorDivision(top, bot);
00881         safe_i64toa(top, buff, bufc);
00882     }
00883 }
00884 
00885 FUNCTION(fun_mod)
00886 {
00887     UNUSED_PARAMETER(executor);
00888     UNUSED_PARAMETER(caller);
00889     UNUSED_PARAMETER(enactor);
00890     UNUSED_PARAMETER(nfargs);
00891     UNUSED_PARAMETER(cargs);
00892     UNUSED_PARAMETER(ncargs);
00893 
00894     INT64 bot, top;
00895 
00896     bot = mux_atoi64(fargs[1]);
00897     if (bot == 0)
00898     {
00899         bot = 1;
00900     }
00901     top = mux_atoi64(fargs[0]);
00902     top = i64Mod(top, bot);
00903     safe_i64toa(top, buff, bufc);
00904 }
00905 
00906 FUNCTION(fun_remainder)
00907 {
00908     UNUSED_PARAMETER(executor);
00909     UNUSED_PARAMETER(caller);
00910     UNUSED_PARAMETER(enactor);
00911     UNUSED_PARAMETER(nfargs);
00912     UNUSED_PARAMETER(cargs);
00913     UNUSED_PARAMETER(ncargs);
00914 
00915     INT64 bot, top;
00916 
00917     bot = mux_atoi64(fargs[1]);
00918     if (bot == 0)
00919     {
00920         bot = 1;
00921     }
00922     top = mux_atoi64(fargs[0]);
00923     top = i64Remainder(top, bot);
00924     safe_i64toa(top, buff, bufc);
00925 }
00926 
00927 /* ---------------------------------------------------------------------------
00928  * fun_abs: Returns the absolute value of its argument.
00929  */
00930 
00931 FUNCTION(fun_abs)
00932 {
00933     UNUSED_PARAMETER(executor);
00934     UNUSED_PARAMETER(caller);
00935     UNUSED_PARAMETER(enactor);
00936     UNUSED_PARAMETER(nfargs);
00937     UNUSED_PARAMETER(cargs);
00938     UNUSED_PARAMETER(ncargs);
00939 
00940     double num = mux_atof(fargs[0]);
00941     if (num == 0.0)
00942     {
00943         safe_chr('0', buff, bufc);
00944     }
00945     else if (num < 0.0)
00946     {
00947         fval(buff, bufc, -num);
00948     }
00949     else
00950     {
00951         fval(buff, bufc, num);
00952     }
00953 }
00954 
00955 // fun_iabs: Returns the absolute value of its argument.
00956 //
00957 FUNCTION(fun_iabs)
00958 {
00959     UNUSED_PARAMETER(executor);
00960     UNUSED_PARAMETER(caller);
00961     UNUSED_PARAMETER(enactor);
00962     UNUSED_PARAMETER(nfargs);
00963     UNUSED_PARAMETER(cargs);
00964     UNUSED_PARAMETER(ncargs);
00965 
00966     INT64 num = mux_atoi64(fargs[0]);
00967 
00968     if (num == 0)
00969     {
00970         safe_chr('0', buff, bufc);
00971     }
00972     else if (num < 0)
00973     {
00974         safe_i64toa(-num, buff, bufc);
00975     }
00976     else
00977     {
00978         safe_i64toa(num, buff, bufc);
00979     }
00980 }
00981 
00982 FUNCTION(fun_dist2d)
00983 {
00984     UNUSED_PARAMETER(executor);
00985     UNUSED_PARAMETER(caller);
00986     UNUSED_PARAMETER(enactor);
00987     UNUSED_PARAMETER(nfargs);
00988     UNUSED_PARAMETER(cargs);
00989     UNUSED_PARAMETER(ncargs);
00990 
00991     double d;
00992     double sum;
00993 
00994     d = mux_atof(fargs[0]) - mux_atof(fargs[2]);
00995     sum  = d * d;
00996     d = mux_atof(fargs[1]) - mux_atof(fargs[3]);
00997     sum += d * d;
00998 
00999     mux_FPRestore();
01000     double result = sqrt(sum);
01001     mux_FPSet();
01002 
01003     fval(buff, bufc, result);
01004 }
01005 
01006 FUNCTION(fun_dist3d)
01007 {
01008     UNUSED_PARAMETER(executor);
01009     UNUSED_PARAMETER(caller);
01010     UNUSED_PARAMETER(enactor);
01011     UNUSED_PARAMETER(nfargs);
01012     UNUSED_PARAMETER(cargs);
01013     UNUSED_PARAMETER(ncargs);
01014 
01015     double d;
01016     double sum;
01017 
01018     d = mux_atof(fargs[0]) - mux_atof(fargs[3]);
01019     sum  = d * d;
01020     d = mux_atof(fargs[1]) - mux_atof(fargs[4]);
01021     sum += d * d;
01022     d = mux_atof(fargs[2]) - mux_atof(fargs[5]);
01023     sum += d * d;
01024 
01025     mux_FPRestore();
01026     double result = sqrt(sum);
01027     mux_FPSet();
01028 
01029     fval(buff, bufc, result);
01030 }
01031 
01032 //------------------------------------------------------------------------
01033 // Vector functions: VADD, VSUB, VMUL, VCROSS, VMAG, VUNIT, VDIM
01034 // Vectors are space-separated numbers.
01035 //
01036 #define VADD_F   0
01037 #define VSUB_F   1
01038 #define VMUL_F   2
01039 #define VDOT_F   3
01040 #define VCROSS_F 4
01041 
01042 static void handle_vectors
01043 (
01044     char *vecarg1, char *vecarg2, char *buff, char **bufc, SEP *psep,
01045     SEP *posep, int flag
01046 )
01047 {
01048     char *v1[(LBUF_SIZE+1)/2], *v2[(LBUF_SIZE+1)/2];
01049     double scalar;
01050     int n, m, i;
01051 
01052     // Split the list up, or return if the list is empty.
01053     //
01054     if (!vecarg1 || !*vecarg1 || !vecarg2 || !*vecarg2)
01055     {
01056         return;
01057     }
01058     n = list2arr(v1, (LBUF_SIZE+1)/2, vecarg1, psep);
01059     m = list2arr(v2, (LBUF_SIZE+1)/2, vecarg2, psep);
01060 
01061     // vmul() and vadd() accepts a scalar in the first or second arg,
01062     // but everything else has to be same-dimensional.
01063     //
01064     if (  n != m
01065        && !(  (  flag == VMUL_F
01066               || flag == VADD_F
01067               || flag == VSUB_F)
01068            && (  n == 1
01069               || m == 1)))
01070     {
01071         safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS", buff, bufc);
01072         return;
01073     }
01074 
01075     switch (flag)
01076     {
01077     case VADD_F:
01078 
01079         // If n or m is 1, this is scalar addition.
01080         // otherwise, add element-wise.
01081         //
01082         if (n == 1)
01083         {
01084             scalar = mux_atof(v1[0]);
01085             for (i = 0; i < m; i++)
01086             {
01087                 if (i != 0)
01088                 {
01089                     print_sep(posep, buff, bufc);
01090                 }
01091                 fval(buff, bufc, mux_atof(v2[i]) + scalar);
01092             }
01093             n = m;
01094         }
01095         else if (m == 1)
01096         {
01097             scalar = mux_atof(v2[0]);
01098             for (i = 0; i < n; i++)
01099             {
01100                 if (i != 0)
01101                 {
01102                     print_sep(posep, buff, bufc);
01103                 }
01104                 fval(buff, bufc, mux_atof(v1[i]) + scalar);
01105             }
01106         }
01107         else
01108         {
01109             for (i = 0; i < n; i++)
01110             {
01111                 if (i != 0)
01112                 {
01113                     print_sep(posep, buff, bufc);
01114                 }
01115                 double a = mux_atof(v1[i]);
01116                 double b = mux_atof(v2[i]);
01117                 fval(buff, bufc, a + b);
01118             }
01119         }
01120         break;
01121 
01122     case VSUB_F:
01123 
01124         if (n == 1)
01125         {
01126             // This is a scalar minus a vector.
01127             //
01128             scalar = mux_atof(v1[0]);
01129             for (i = 0; i < m; i++)
01130             {
01131                 if (i != 0)
01132                 {
01133                     print_sep(posep, buff, bufc);
01134                 }
01135                 fval(buff, bufc, scalar - mux_atof(v2[i]));
01136             }
01137         }
01138         else if (m == 1)
01139         {
01140             // This is a vector minus a scalar.
01141             //
01142             scalar = mux_atof(v2[0]);
01143             for (i = 0; i < n; i++)
01144             {
01145                 if (i != 0)
01146                 {
01147                     print_sep(posep, buff, bufc);
01148                 }
01149                 fval(buff, bufc, mux_atof(v1[i]) - scalar);
01150             }
01151         }
01152         else
01153         {
01154             // This is a vector minus a vector.
01155             //
01156             for (i = 0; i < n; i++)
01157             {
01158                 if (i != 0)
01159                 {
01160                     print_sep(posep, buff, bufc);
01161                 }
01162                 double a = mux_atof(v1[i]);
01163                 double b = mux_atof(v2[i]);
01164                 fval(buff, bufc, a - b);
01165             }
01166         }
01167         break;
01168 
01169     case VMUL_F:
01170 
01171         // If n or m is 1, this is scalar multiplication.
01172         // otherwise, multiply elementwise.
01173         //
01174         if (n == 1)
01175         {
01176             scalar = mux_atof(v1[0]);
01177             for (i = 0; i < m; i++)
01178             {
01179                 if (i != 0)
01180                 {
01181                     print_sep(posep, buff, bufc);
01182                 }
01183                 fval(buff, bufc, mux_atof(v2[i]) * scalar);
01184             }
01185         }
01186         else if (m == 1)
01187         {
01188             scalar = mux_atof(v2[0]);
01189             for (i = 0; i < n; i++)
01190             {
01191                 if (i != 0)
01192                 {
01193                     print_sep(posep, buff, bufc);
01194                 }
01195                 fval(buff, bufc, mux_atof(v1[i]) * scalar);
01196             }
01197         }
01198         else
01199         {
01200             // Vector element-wise product.
01201             //
01202             for (i = 0; i < n; i++)
01203             {
01204                 if (i != 0)
01205                 {
01206                     print_sep(posep, buff, bufc);
01207                 }
01208                 double a = mux_atof(v1[i]);
01209                 double b = mux_atof(v2[i]);
01210                 fval(buff, bufc, a * b);
01211             }
01212         }
01213         break;
01214 
01215     case VDOT_F:
01216 
01217         scalar = 0.0;
01218         for (i = 0; i < n; i++)
01219         {
01220             double a = mux_atof(v1[i]);
01221             double b = mux_atof(v2[i]);
01222             scalar +=  a * b;
01223         }
01224         fval(buff, bufc, scalar);
01225         break;
01226 
01227     case VCROSS_F:
01228 
01229         // cross product: (a,b,c) x (d,e,f) = (bf - ce, cd - af, ae - bd)
01230         //
01231         // Or in other words:
01232         //
01233         //      | a  b  c |
01234         //  det | d  e  f | = i(bf-ce) + j(cd-af) + k(ae-bd)
01235         //      | i  j  k |
01236         //
01237         // where i, j, and k are unit vectors in the x, y, and z
01238         // cartisian coordinate space and are understood when expressed
01239         // in vector form.
01240         //
01241         if (n != 3)
01242         {
01243             safe_str("#-1 VECTORS MUST BE DIMENSION OF 3", buff, bufc);
01244         }
01245         else
01246         {
01247             double a[2][3];
01248             for (i = 0; i < 3; i++)
01249             {
01250                 a[0][i] = mux_atof(v1[i]);
01251                 a[1][i] = mux_atof(v2[i]);
01252             }
01253             fval(buff, bufc, (a[0][1] * a[1][2]) - (a[0][2] * a[1][1]));
01254             print_sep(posep, buff, bufc);
01255             fval(buff, bufc, (a[0][2] * a[1][0]) - (a[0][0] * a[1][2]));
01256             print_sep(posep, buff, bufc);
01257             fval(buff, bufc, (a[0][0] * a[1][1]) - (a[0][1] * a[1][0]));
01258         }
01259         break;
01260 
01261     default:
01262 
01263         // If we reached this, we're in trouble.
01264         //
01265         safe_str("#-1 UNIMPLEMENTED", buff, bufc);
01266     }
01267 }
01268 
01269 FUNCTION(fun_vadd)
01270 {
01271     SEP sep;
01272     if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
01273     {
01274         return;
01275     }
01276 
01277     SEP osep = sep;
01278     if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
01279     {
01280         return;
01281     }
01282     handle_vectors(fargs[0], fargs[1], buff, bufc, &sep, &osep, VADD_F);
01283 }
01284 
01285 FUNCTION(fun_vsub)
01286 {
01287     SEP sep;
01288     if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
01289     {
01290         return;
01291     }
01292 
01293     SEP osep = sep;
01294     if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
01295     {
01296         return;
01297     }
01298     handle_vectors(fargs[0], fargs[1], buff, bufc, &sep, &osep, VSUB_F);
01299 }
01300 
01301 FUNCTION(fun_vmul)
01302 {
01303     SEP sep;
01304     if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
01305     {
01306         return;
01307     }
01308 
01309     SEP osep = sep;
01310     if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
01311     {
01312         return;
01313     }
01314     handle_vectors(fargs[0], fargs[1], buff, bufc, &sep, &osep, VMUL_F);
01315 }
01316 
01317 FUNCTION(fun_vdot)
01318 {
01319     // dot product: (a,b,c) . (d,e,f) = ad + be + cf
01320     //
01321     SEP sep;
01322     if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
01323     {
01324         return;
01325     }
01326 
01327     SEP osep = sep;
01328     if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
01329     {
01330         return;
01331     }
01332     handle_vectors(fargs[0], fargs[1], buff, bufc, &sep, &osep, VDOT_F);
01333 }
01334 
01335 FUNCTION(fun_vcross)
01336 {
01337     // cross product: (a,b,c) x (d,e,f) = (bf - ce, cd - af, ae - bd)
01338     //
01339     SEP sep;
01340     if (!OPTIONAL_DELIM(3, sep, DELIM_DFLT|DELIM_STRING))
01341     {
01342         return;
01343     }
01344 
01345     SEP osep = sep;
01346     if (!OPTIONAL_DELIM(4, osep, DELIM_NULL|DELIM_CRLF|DELIM_STRING|DELIM_INIT))
01347     {
01348         return;
01349     }
01350     handle_vectors(fargs[0], fargs[1], buff, bufc, &sep, &osep, VCROSS_F);
01351 }
01352 
01353 FUNCTION(fun_vmag)
01354 {
01355     SEP sep;
01356     if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
01357     {
01358         return;
01359     }
01360 
01361     char *v1[LBUF_SIZE];
01362     int n, i;
01363     double tmp, res = 0.0;
01364 
01365     // Split the list up, or return if the list is empty.
01366     //
01367     if (!fargs[0] || !*fargs[0])
01368     {
01369         return;
01370     }
01371     n = list2arr(v1, LBUF_SIZE, fargs[0], &sep);
01372 
01373     // Calculate the magnitude.
01374     //
01375     for (i = 0; i < n; i++)
01376     {
01377         tmp = mux_atof(v1[i]);
01378         res += tmp * tmp;
01379     }
01380 
01381     if (res > 0)
01382     {
01383         mux_FPRestore();
01384         double result = sqrt(res);
01385         mux_FPSet();
01386 
01387         fval(buff, bufc, result);
01388     }
01389     else
01390     {
01391         safe_chr('0', buff, bufc);
01392     }
01393 }
01394 
01395 FUNCTION(fun_vunit)
01396 {
01397     SEP sep;
01398     if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
01399     {
01400         return;
01401     }
01402 
01403     char *v1[LBUF_SIZE];
01404     int n, i;
01405     double tmp, res = 0.0;
01406 
01407     // Split the list up, or return if the list is empty.
01408     //
01409     if (!fargs[0] || !*fargs[0])
01410     {
01411         return;
01412     }
01413     n = list2arr(v1, LBUF_SIZE, fargs[0], &sep);
01414 
01415     // Calculate the magnitude.
01416     //
01417     for (i = 0; i < n; i++)
01418     {
01419         tmp = mux_atof(v1[i]);
01420         res += tmp * tmp;
01421     }
01422 
01423     if (res <= 0)
01424     {
01425         safe_str("#-1 CAN'T MAKE UNIT VECTOR FROM ZERO-LENGTH VECTOR",
01426             buff, bufc);
01427         return;
01428     }
01429     for (i = 0; i < n; i++)
01430     {
01431         if (i != 0)
01432         {
01433             print_sep(&sep, buff, bufc);
01434         }
01435 
01436         mux_FPRestore();
01437         double result = sqrt(res);
01438         mux_FPSet();
01439 
01440         fval(buff, bufc, mux_atof(v1[i]) / result);
01441     }
01442 }
01443 
01444 FUNCTION(fun_floor)
01445 {
01446     UNUSED_PARAMETER(executor);
01447     UNUSED_PARAMETER(caller);
01448     UNUSED_PARAMETER(enactor);
01449     UNUSED_PARAMETER(nfargs);
01450     UNUSED_PARAMETER(cargs);
01451     UNUSED_PARAMETER(ncargs);
01452 
01453     mux_FPRestore();
01454     double r = floor(mux_atof(fargs[0]));
01455     mux_FPSet();
01456 
01457 #ifdef HAVE_IEEE_FP_FORMAT
01458     int fpc = mux_fpclass(r);
01459     if (MUX_FPGROUP(fpc) == MUX_FPGROUP_PASS)
01460     {
01461 #endif // HAVE_IEEE_FP_FORMAT
01462         safe_tprintf_str(buff, bufc, "%.0f", r);
01463 #ifdef HAVE_IEEE_FP_FORMAT
01464     }
01465     else
01466     {
01467         safe_str(mux_FPStrings[MUX_FPCLASS(fpc)], buff, bufc);
01468     }
01469 #endif // HAVE_IEEE_FP_FORMAT
01470 }
01471 
01472 FUNCTION(fun_ceil)
01473 {
01474     UNUSED_PARAMETER(executor);
01475     UNUSED_PARAMETER(caller);
01476     UNUSED_PARAMETER(enactor);
01477     UNUSED_PARAMETER(nfargs);
01478     UNUSED_PARAMETER(cargs);
01479     UNUSED_PARAMETER(ncargs);
01480 
01481     mux_FPRestore();
01482     double r = ceil(mux_atof(fargs[0]));
01483     mux_FPSet();
01484 
01485 #ifdef HAVE_IEEE_FP_FORMAT
01486     int fpc = mux_fpclass(r);
01487     if (MUX_FPGROUP(fpc) == MUX_FPGROUP_PASS)
01488     {
01489 #endif // HAVE_IEEE_FP_FORMAT
01490         safe_tprintf_str(buff, bufc, "%.0f", r);
01491 #ifdef HAVE_IEEE_FP_FORMAT
01492     }
01493     else
01494     {
01495         safe_str(mux_FPStrings[MUX_FPCLASS(fpc)], buff, bufc);
01496     }
01497 #endif // HAVE_IEEE_FP_FORMAT
01498 }
01499 
01500 FUNCTION(fun_round)
01501 {
01502     UNUSED_PARAMETER(executor);
01503     UNUSED_PARAMETER(caller);
01504     UNUSED_PARAMETER(enactor);
01505     UNUSED_PARAMETER(nfargs);
01506     UNUSED_PARAMETER(cargs);
01507     UNUSED_PARAMETER(ncargs);
01508 
01509     double r = mux_atof(fargs[0]);
01510 #ifdef HAVE_IEEE_FP_FORMAT
01511     int fpc = mux_fpclass(r);
01512     if (  MUX_FPGROUP(fpc) == MUX_FPGROUP_PASS
01513        || MUX_FPGROUP(fpc) == MUX_FPGROUP_ZERO)
01514     {
01515         if (MUX_FPGROUP(fpc) == MUX_FPGROUP_ZERO)
01516         {
01517             r = 0.0;
01518         }
01519 #endif // HAVE_IEEE_FP_FORMAT
01520         int frac = mux_atol(fargs[1]);
01521         safe_str(mux_ftoa(r, true, frac), buff, bufc);
01522 #ifdef HAVE_IEEE_FP_FORMAT
01523     }
01524     else
01525     {
01526         safe_str(mux_FPStrings[MUX_FPCLASS(fpc)], buff, bufc);
01527     }
01528 #endif // HAVE_IEEE_FP_FORMAT
01529 }
01530 
01531 FUNCTION(fun_pi)
01532 {
01533     UNUSED_PARAMETER(executor);
01534     UNUSED_PARAMETER(caller);
01535     UNUSED_PARAMETER(enactor);
01536     UNUSED_PARAMETER(fargs);
01537     UNUSED_PARAMETER(nfargs);
01538     UNUSED_PARAMETER(cargs);
01539     UNUSED_PARAMETER(ncargs);
01540 
01541     safe_str("3.141592653589793", buff, bufc);
01542 }
01543 
01544 FUNCTION(fun_e)
01545 {
01546     UNUSED_PARAMETER(executor);
01547     UNUSED_PARAMETER(caller);
01548     UNUSED_PARAMETER(enactor);
01549     UNUSED_PARAMETER(fargs);
01550     UNUSED_PARAMETER(nfargs);
01551     UNUSED_PARAMETER(cargs);
01552     UNUSED_PARAMETER(ncargs);
01553 
01554     safe_str("2.718281828459045", buff, bufc);
01555 }
01556 
01557 static double ConvertRDG2R(double d, const char *szUnits)
01558 {
01559     switch (mux_tolower(szUnits[0]))
01560     {
01561     case 'd':
01562         // Degrees to Radians.
01563         //
01564         d *= 0.017453292519943295;
01565         break;
01566 
01567     case 'g':
01568         // Gradians to Radians.
01569         //
01570         d *= 0.015707963267948967;
01571         break;
01572     }
01573     return d;
01574 }
01575 
01576 static double ConvertR2RDG(double d, const char *szUnits)
01577 {
01578     switch (mux_tolower(szUnits[0]))
01579     {
01580     case 'd':
01581         // Radians to Degrees.
01582         //
01583         d *= 57.29577951308232;
01584         break;
01585 
01586     case 'g':
01587         // Radians to Gradians.
01588         //
01589         d *= 63.66197723675813;
01590         break;
01591     }
01592     return d;
01593 }
01594 
01595 FUNCTION(fun_ctu)
01596 {
01597     UNUSED_PARAMETER(executor);
01598     UNUSED_PARAMETER(caller);
01599     UNUSED_PARAMETER(enactor);
01600     UNUSED_PARAMETER(nfargs);
01601     UNUSED_PARAMETER(cargs);
01602     UNUSED_PARAMETER(ncargs);
01603 
01604     double val = mux_atof(fargs[0]);
01605     val = ConvertRDG2R(val, fargs[1]);
01606     val = ConvertR2RDG(val, fargs[2]);
01607     fval(buff, bufc, val);
01608 }
01609 
01610 FUNCTION(fun_sin)
01611 {
01612     UNUSED_PARAMETER(executor);
01613     UNUSED_PARAMETER(caller);
01614     UNUSED_PARAMETER(enactor);
01615     UNUSED_PARAMETER(cargs);
01616     UNUSED_PARAMETER(ncargs);
01617 
01618     double d = mux_atof(fargs[0]);
01619     if (nfargs == 2)
01620     {
01621         d = ConvertRDG2R(d, fargs[1]);
01622     }
01623 
01624     mux_FPRestore();
01625     d = sin(d);
01626     mux_FPSet();
01627 
01628     fval(buff, bufc, d);
01629 }
01630 
01631 FUNCTION(fun_cos)
01632 {
01633     UNUSED_PARAMETER(executor);
01634     UNUSED_PARAMETER(caller);
01635     UNUSED_PARAMETER(enactor);
01636     UNUSED_PARAMETER(cargs);
01637     UNUSED_PARAMETER(ncargs);
01638 
01639     double d = mux_atof(fargs[0]);
01640     if (nfargs == 2)
01641     {
01642         d = ConvertRDG2R(d, fargs[1]);
01643     }
01644 
01645     mux_FPRestore();
01646     d = cos(d);
01647     mux_FPSet();
01648 
01649     fval(buff, bufc, d);
01650 }
01651 
01652 FUNCTION(fun_tan)
01653 {
01654     UNUSED_PARAMETER(executor);
01655     UNUSED_PARAMETER(caller);
01656     UNUSED_PARAMETER(enactor);
01657     UNUSED_PARAMETER(cargs);
01658     UNUSED_PARAMETER(ncargs);
01659 
01660     double d = mux_atof(fargs[0]);
01661     if (nfargs == 2)
01662     {
01663         d = ConvertRDG2R(d, fargs[1]);
01664     }
01665 
01666     mux_FPRestore();
01667     d = tan(d);
01668     mux_FPSet();
01669 
01670     fval(buff, bufc, d);
01671 }
01672 
01673 FUNCTION(fun_asin)
01674 {
01675     UNUSED_PARAMETER(executor);
01676     UNUSED_PARAMETER(caller);
01677     UNUSED_PARAMETER(enactor);
01678     UNUSED_PARAMETER(cargs);
01679     UNUSED_PARAMETER(ncargs);
01680 
01681     double val = mux_atof(fargs[0]);
01682 #ifndef HAVE_IEEE_FP_SNAN
01683     if ((val < -1.0) || (val > 1.0))
01684     {
01685         safe_str("Ind", buff, bufc);
01686         return;
01687     }
01688 #endif
01689     mux_FPRestore();
01690     val = asin(val);
01691     mux_FPSet();
01692 
01693     if (nfargs == 2)
01694     {
01695         val = ConvertR2RDG(val, fargs[1]);
01696     }
01697     fval(buff, bufc, val);
01698 }
01699 
01700 FUNCTION(fun_acos)
01701 {
01702     UNUSED_PARAMETER(executor);
01703     UNUSED_PARAMETER(caller);
01704     UNUSED_PARAMETER(enactor);
01705     UNUSED_PARAMETER(cargs);
01706     UNUSED_PARAMETER(ncargs);
01707 
01708     double val = mux_atof(fargs[0]);
01709 #ifndef HAVE_IEEE_FP_SNAN
01710     if ((val < -1.0) || (val > 1.0))
01711     {
01712         safe_str("Ind", buff, bufc);
01713         return;
01714     }
01715 #endif
01716     mux_FPRestore();
01717     val = acos(val);
01718     mux_FPSet();
01719 
01720     if (nfargs == 2)
01721     {
01722         val = ConvertR2RDG(val, fargs[1]);
01723     }
01724     fval(buff, bufc, val);
01725 }
01726 
01727 FUNCTION(fun_atan)
01728 {
01729     UNUSED_PARAMETER(executor);
01730     UNUSED_PARAMETER(caller);
01731     UNUSED_PARAMETER(enactor);
01732     UNUSED_PARAMETER(cargs);
01733     UNUSED_PARAMETER(ncargs);
01734 
01735     double val = mux_atof(fargs[0]);
01736 
01737     mux_FPRestore();
01738     val = atan(val);
01739     mux_FPSet();
01740 
01741     if (nfargs == 2)
01742     {
01743         val = ConvertR2RDG(val, fargs[1]);
01744     }
01745     fval(buff, bufc, val);
01746 }
01747 
01748 FUNCTION(fun_exp)
01749 {
01750     UNUSED_PARAMETER(executor);
01751     UNUSED_PARAMETER(caller);
01752     UNUSED_PARAMETER(enactor);
01753     UNUSED_PARAMETER(nfargs);
01754     UNUSED_PARAMETER(cargs);
01755     UNUSED_PARAMETER(ncargs);
01756 
01757     double val = mux_atof(fargs[0]);
01758 
01759     mux_FPRestore();
01760     val = exp(val);
01761     mux_FPSet();
01762 
01763     fval(buff, bufc, val);
01764 }
01765 
01766 FUNCTION(fun_power)
01767 {
01768     UNUSED_PARAMETER(executor);
01769     UNUSED_PARAMETER(caller);
01770     UNUSED_PARAMETER(enactor);
01771     UNUSED_PARAMETER(nfargs);
01772     UNUSED_PARAMETER(cargs);
01773     UNUSED_PARAMETER(ncargs);
01774 
01775     double val, val1, val2;
01776 
01777     val1 = mux_atof(fargs[0]);
01778     val2 = mux_atof(fargs[1]);
01779 #ifndef HAVE_IEEE_FP_SNAN
01780     if (val1 < 0.0)
01781     {
01782         safe_str("Ind", buff, bufc);
01783     }
01784     else
01785     {
01786         mux_FPRestore();
01787         val = pow(val1, val2);
01788         mux_FPSet();
01789         fval(buff, bufc, val);
01790     }
01791 #else
01792     mux_FPRestore();
01793     val = pow(val1, val2);
01794     mux_FPSet();
01795     fval(buff, bufc, val);
01796 #endif
01797 }
01798 
01799 FUNCTION(fun_fmod)
01800 {
01801     UNUSED_PARAMETER(executor);
01802     UNUSED_PARAMETER(caller);
01803     UNUSED_PARAMETER(enactor);
01804     UNUSED_PARAMETER(nfargs);
01805     UNUSED_PARAMETER(cargs);
01806     UNUSED_PARAMETER(ncargs);
01807 
01808     double val, val1, val2;
01809 
01810     val1 = mux_atof(fargs[0]);
01811     val2 = mux_atof(fargs[1]);
01812 #ifndef HAVE_IEEE_FP_SNAN
01813     if (val1 == 0.0)
01814     {
01815         safe_str("Ind", buff, bufc);
01816     }
01817     else
01818     {
01819         mux_FPRestore();
01820         val = fmod(val1, val2);
01821         mux_FPSet();
01822         fval(buff, bufc, val);
01823     }
01824 #else
01825     mux_FPRestore();
01826     val = fmod(val1, val2);
01827     mux_FPSet();
01828     fval(buff, bufc, val);
01829 #endif
01830 }
01831 
01832 FUNCTION(fun_ln)
01833 {
01834     UNUSED_PARAMETER(executor);
01835     UNUSED_PARAMETER(caller);
01836     UNUSED_PARAMETER(enactor);
01837     UNUSED_PARAMETER(nfargs);
01838     UNUSED_PARAMETER(cargs);
01839     UNUSED_PARAMETER(ncargs);
01840 
01841     double val;
01842 
01843     val = mux_atof(fargs[0]);
01844 #ifndef HAVE_IEEE_FP_SNAN
01845     if (val < 0.0)
01846     {
01847         safe_str("Ind", buff, bufc);
01848     }
01849     else if (val == 0.0)
01850     {
01851         safe_str("-Inf", buff, bufc);
01852     }
01853     else
01854     {
01855         mux_FPRestore();
01856         val = log(val);
01857         mux_FPSet();
01858     }
01859 #else
01860     mux_FPRestore();
01861     val = log(val);
01862     mux_FPSet();
01863 #endif
01864     fval(buff, bufc, val);
01865 }
01866 
01867 FUNCTION(fun_log)
01868 {
01869     UNUSED_PARAMETER(executor);
01870     UNUSED_PARAMETER(caller);
01871     UNUSED_PARAMETER(enactor);
01872     UNUSED_PARAMETER(nfargs);
01873     UNUSED_PARAMETER(cargs);
01874     UNUSED_PARAMETER(ncargs);
01875 
01876     double val;
01877 
01878     val = mux_atof(fargs[0]);
01879 #ifndef HAVE_IEEE_FP_SNAN
01880     if (val < 0.0)
01881     {
01882         safe_str("Ind", buff, bufc);
01883     }
01884     else if (val == 0.0)
01885     {
01886         safe_str("-Inf", buff, bufc);
01887     }
01888     else
01889     {
01890         mux_FPRestore();
01891         val = log10(val);
01892         mux_FPSet();
01893     }
01894 #else
01895     mux_FPRestore();
01896     val = log10(val);
01897     mux_FPSet();
01898 #endif
01899     fval(buff, bufc, val);
01900 }
01901 
01902 FUNCTION(fun_sqrt)
01903 {
01904     UNUSED_PARAMETER(executor);
01905     UNUSED_PARAMETER(caller);
01906     UNUSED_PARAMETER(enactor);
01907     UNUSED_PARAMETER(nfargs);
01908     UNUSED_PARAMETER(cargs);
01909     UNUSED_PARAMETER(ncargs);
01910 
01911     double val;
01912 
01913     val = mux_atof(fargs[0]);
01914 #ifndef HAVE_IEEE_FP_SNAN
01915     if (val < 0.0)
01916     {
01917         safe_str("Ind", buff, bufc);
01918     }
01919     else if (val == 0.0)
01920     {
01921         safe_chr('0', buff, bufc);
01922     }
01923     else
01924     {
01925         mux_FPRestore();
01926         val = sqrt(val);
01927         mux_FPSet();
01928     }
01929 #else
01930     mux_FPRestore();
01931     val = sqrt(val);
01932     mux_FPSet();
01933 #endif
01934     fval(buff, bufc, val);
01935 }
01936 
01937 /* ---------------------------------------------------------------------------
01938  * isnum: is the argument a number?
01939  */
01940 
01941 FUNCTION(fun_isnum)
01942 {
01943     UNUSED_PARAMETER(executor);
01944     UNUSED_PARAMETER(caller);
01945     UNUSED_PARAMETER(enactor);
01946     UNUSED_PARAMETER(nfargs);
01947     UNUSED_PARAMETER(cargs);
01948     UNUSED_PARAMETER(ncargs);
01949 
01950     safe_bool(is_real(fargs[0]), buff, bufc);
01951 }
01952 
01953 /* ---------------------------------------------------------------------------
01954  * israt: is the argument an rational?
01955  */
01956 
01957 FUNCTION(fun_israt)
01958 {
01959     UNUSED_PARAMETER(executor);
01960     UNUSED_PARAMETER(caller);
01961     UNUSED_PARAMETER(enactor);
01962     UNUSED_PARAMETER(nfargs);
01963     UNUSED_PARAMETER(cargs);
01964     UNUSED_PARAMETER(ncargs);
01965 
01966     safe_bool(is_rational(fargs[0]), buff, bufc);
01967 }
01968 
01969 /* ---------------------------------------------------------------------------
01970  * isint: is the argument an integer?
01971  */
01972 
01973 FUNCTION(fun_isint)
01974 {
01975     UNUSED_PARAMETER(executor);
01976     UNUSED_PARAMETER(caller);
01977     UNUSED_PARAMETER(enactor);
01978     UNUSED_PARAMETER(nfargs);
01979     UNUSED_PARAMETER(cargs);
01980     UNUSED_PARAMETER(ncargs);
01981 
01982     safe_bool(is_integer(fargs[0], NULL), buff, bufc);
01983 }
01984 
01985 FUNCTION(fun_and)
01986 {
01987     UNUSED_PARAMETER(executor);
01988     UNUSED_PARAMETER(caller);
01989     UNUSED_PARAMETER(enactor);
01990     UNUSED_PARAMETER(cargs);
01991     UNUSED_PARAMETER(ncargs);
01992 
01993     bool val = true;
01994     for (int i = 0; i < nfargs && val; i++)
01995     {
01996         val = isTRUE(mux_atol(fargs[i]));
01997     }
01998     safe_bool(val, buff, bufc);
01999 }
02000 
02001 FUNCTION(fun_or)
02002 {
02003     UNUSED_PARAMETER(executor);
02004     UNUSED_PARAMETER(caller);
02005     UNUSED_PARAMETER(enactor);
02006     UNUSED_PARAMETER(cargs);
02007     UNUSED_PARAMETER(ncargs);
02008 
02009     bool val = false;
02010     for (int i = 0; i < nfargs && !val; i++)
02011     {
02012         val = isTRUE(mux_atol(fargs[i]));
02013     }
02014     safe_bool(val, buff, bufc);
02015 }
02016 
02017 FUNCTION(fun_andbool)
02018 {
02019     UNUSED_PARAMETER(executor);
02020     UNUSED_PARAMETER(caller);
02021     UNUSED_PARAMETER(enactor);
02022     UNUSED_PARAMETER(cargs);
02023     UNUSED_PARAMETER(ncargs);
02024 
02025     bool val = true;
02026     for (int i = 0; i < nfargs && val; i++)
02027     {
02028         val = xlate(fargs[i]);
02029     }
02030     safe_bool(val, buff, bufc);
02031 }
02032 
02033 FUNCTION(fun_orbool)
02034 {
02035     UNUSED_PARAMETER(executor);
02036     UNUSED_PARAMETER(caller);
02037     UNUSED_PARAMETER(enactor);
02038     UNUSED_PARAMETER(cargs);
02039     UNUSED_PARAMETER(ncargs);
02040 
02041     bool val = false;
02042     for (int i = 0; i < nfargs && !val; i++)
02043     {
02044         val = xlate(fargs[i]);
02045     }
02046     safe_bool(val, buff, bufc);
02047 }
02048 
02049 FUNCTION(fun_cand)
02050 {
02051     bool val = true;
02052     char *temp = alloc_lbuf("fun_cand");
02053     for (int i = 0; i < nfargs && val && !MuxAlarm.bAlarmed; i++)
02054     {
02055         char *bp = temp;
02056         char *str = fargs[i];
02057         mux_exec(temp, &bp, executor, caller, enactor,
02058             EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
02059         *bp = '\0';
02060         val = isTRUE(mux_atol(temp));
02061     }
02062     free_lbuf(temp);
02063     safe_bool(val, buff, bufc);
02064 }
02065 
02066 FUNCTION(fun_cor)
02067 {
02068     bool val = false;
02069     char *temp = alloc_lbuf("fun_cor");
02070     for (int i = 0; i < nfargs && !val && !MuxAlarm.bAlarmed; i++)
02071     {
02072         char *bp = temp;
02073         char *str = fargs[i];
02074         mux_exec(temp, &bp, executor, caller, enactor,
02075             EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
02076         *bp = '\0';
02077         val = isTRUE(mux_atol(temp));
02078     }
02079     free_lbuf(temp);
02080     safe_bool(val, buff, bufc);
02081 }
02082 
02083 FUNCTION(fun_candbool)
02084 {
02085     bool val = true;
02086     char *temp = alloc_lbuf("fun_candbool");
02087     for (int i = 0; i < nfargs && val && !MuxAlarm.bAlarmed; i++)
02088     {
02089         char *bp = temp;
02090         char *str = fargs[i];
02091         mux_exec(temp, &bp, executor, caller, enactor,
02092             EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
02093         *bp = '\0';
02094         val = xlate(temp);
02095     }
02096     free_lbuf(temp);
02097     safe_bool(val, buff, bufc);
02098 }
02099 
02100 FUNCTION(fun_corbool)
02101 {
02102     bool val = false;
02103     char *temp = alloc_lbuf("fun_corbool");
02104     for (int i = 0; i < nfargs && !val && !MuxAlarm.bAlarmed; i++)
02105     {
02106         char *bp = temp;
02107         char *str = fargs[i];
02108         mux_exec(temp, &bp, executor, caller, enactor,
02109             EV_STRIP_CURLY | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
02110         *bp = '\0';
02111         val = xlate(temp);
02112     }
02113     free_lbuf(temp);
02114     safe_bool(val, buff, bufc);
02115 }
02116 
02117 FUNCTION(fun_xor)
02118 {
02119     UNUSED_PARAMETER(executor);
02120     UNUSED_PARAMETER(caller);
02121     UNUSED_PARAMETER(enactor);
02122     UNUSED_PARAMETER(cargs);
02123     UNUSED_PARAMETER(ncargs);
02124 
02125     bool val = false;
02126     for (int i = 0; i < nfargs; i++)
02127     {
02128         int tval = mux_atol(fargs[i]);
02129         val = (val && !tval) || (!val && tval);
02130     }
02131     safe_bool(val, buff, bufc);
02132 }
02133 
02134 FUNCTION(fun_not)
02135 {
02136     UNUSED_PARAMETER(executor);
02137     UNUSED_PARAMETER(caller);
02138     UNUSED_PARAMETER(enactor);
02139     UNUSED_PARAMETER(nfargs);
02140     UNUSED_PARAMETER(cargs);
02141     UNUSED_PARAMETER(ncargs);
02142 
02143     safe_bool(!xlate(fargs[0]), buff, bufc);
02144 }
02145 
02146 FUNCTION(fun_t)
02147 {
02148     UNUSED_PARAMETER(executor);
02149     UNUSED_PARAMETER(caller);
02150     UNUSED_PARAMETER(enactor);
02151     UNUSED_PARAMETER(cargs);
02152     UNUSED_PARAMETER(ncargs);
02153 
02154     if (  nfargs <= 0
02155        || fargs[0][0] == '\0')
02156     {
02157         safe_chr('0', buff, bufc);
02158     }
02159     else
02160     {
02161         safe_bool(xlate(fargs[0]), buff, bufc);
02162     }
02163 }
02164 static const char *bigones[] =
02165 {
02166     "",
02167     "thousand",
02168     "million",
02169     "billion",
02170     "trillion"
02171 };
02172 
02173 static const char *singles[] =
02174 {
02175     "",
02176     "one",
02177     "two",
02178     "three",
02179     "four",
02180     "five",
02181     "six",
02182     "seven",
02183     "eight",
02184     "nine"
02185 };
02186 
02187 static const char *teens[] =
02188 {
02189     "ten",
02190     "eleven",
02191     "twelve",
02192     "thirteen",
02193     "fourteen",
02194     "fifteen",
02195     "sixteen",
02196     "seventeen",
02197     "eighteen",
02198     "nineteen"
02199 };
02200 
02201 static const char *tens[] =
02202 {
02203     "",
02204     "",
02205     "twenty",
02206     "thirty",
02207     "forty",
02208     "fifty",
02209     "sixty",
02210     "seventy",
02211     "eighty",
02212     "ninety"
02213 };
02214 
02215 static const char *th_prefix[] =
02216 {
02217     "",
02218     "ten",
02219     "hundred"
02220 };
02221 
02222 class CSpellNum
02223 {
02224 public:
02225     void SpellNum(const char *p, char *buff_arg, char **bufc_arg);
02226 
02227 private:
02228     void TwoDigits(const char *p);
02229     void ThreeDigits(const char *p, int iBigOne);
02230     void ManyDigits(int n, const char *p, bool bHundreds);
02231     void FractionalDigits(int n, const char *p);
02232 
02233     void StartWord(void);
02234     void AddWord(const char *p);
02235 
02236     char *buff;
02237     char **bufc;
02238     bool bNeedSpace;
02239 };
02240 
02241 void CSpellNum::StartWord(void)
02242 {
02243     if (bNeedSpace)
02244     {
02245         safe_chr(' ', buff, bufc);
02246     }
02247     bNeedSpace = true;
02248 }
02249 
02250 void CSpellNum::AddWord(const char *p)
02251 {
02252     safe_str(p, buff, bufc);
02253 }
02254 
02255 // Handle two-character sequences.
02256 //
02257 void CSpellNum::TwoDigits(const char *p)
02258 {
02259     int n0 = p[0] - '0';
02260     int n1 = p[1] - '0';
02261 
02262     if (n0 == 0)
02263     {
02264         if (n1 != 0)
02265         {
02266             StartWord();
02267             AddWord(singles[n1]);
02268         }
02269         return;
02270     }
02271     else if (n0 == 1)
02272     {
02273         StartWord();
02274         AddWord(teens[n1]);
02275         return;
02276     }
02277     if (n1 == 0)
02278     {
02279         StartWord();
02280         AddWord(tens[n0]);
02281     }
02282     else
02283     {
02284         StartWord();
02285         AddWord(tens[n0]);
02286         AddWord("-");
02287         AddWord(singles[n1]);
02288     }
02289 }
02290 
02291 // Handle three-character sequences.
02292 //
02293 void CSpellNum::ThreeDigits(const char *p, int iBigOne)
02294 {
02295     if (  p[0] == '0'
02296        && p[1] == '0'
02297        && p[2] == '0')
02298     {
02299         return;
02300     }
02301 
02302     // Handle hundreds.
02303     //
02304     if (p[0] != '0')
02305     {
02306         StartWord();
02307         AddWord(singles[p[0]-'0']);
02308         StartWord();
02309         AddWord("hundred");
02310     }
02311     TwoDigits(p+1);
02312     if (iBigOne > 0)
02313     {
02314         StartWord();
02315         AddWord(bigones[iBigOne]);
02316     }
02317 }
02318 
02319 // Handle a series of patterns of three.
02320 //
02321 void CSpellNum::ManyDigits(int n, const char *p, bool bHundreds)
02322 {
02323     // Handle special Hundreds cases.
02324     //
02325     if (  bHundreds
02326        && n == 4
02327        && p[1] != '0')
02328     {
02329         TwoDigits(p);
02330         StartWord();
02331         AddWord("hundred");
02332         TwoDigits(p+2);
02333         return;
02334     }
02335 
02336     // Handle normal cases.
02337     //
02338     int ndiv = ((n + 2) / 3) - 1;
02339     int nrem = n % 3;
02340     char buf[3];
02341     if (nrem == 0)
02342     {
02343         nrem = 3;
02344     }
02345 
02346     int j = nrem;
02347     for (int i = 2; 0 <= i; i--)
02348     {
02349         if (j)
02350         {
02351             j--;
02352             buf[i] = p[j];
02353         }
02354         else
02355         {
02356             buf[i] = '0';
02357         }
02358     }
02359     ThreeDigits(buf, ndiv);
02360     p += nrem;
02361     while (ndiv-- > 0)
02362     {
02363         ThreeDigits(p, ndiv);
02364         p += 3;
02365     }
02366 }
02367 
02368 // Handle precision ending for part to the right of the decimal place.
02369 //
02370 void CSpellNum::FractionalDigits(int n, const char *p)
02371 {
02372     ManyDigits(n, p, false);
02373     if (  0 < n
02374        && n < 15)
02375     {
02376         int d = n / 3;
02377         int r = n % 3;
02378         StartWord();
02379         if (r != 0)
02380         {
02381             AddWord(th_prefix[r]);
02382             if (d != 0)
02383             {
02384                 AddWord("-");
02385             }
02386         }
02387         AddWord(bigones[d]);
02388         AddWord("th");
02389         INT64 i64 = mux_atoi64(p);
02390         if (i64 != 1)
02391         {
02392             AddWord("s");
02393         }
02394     }
02395 }
02396 
02397 void CSpellNum::SpellNum(const char *number, char *buff_arg, char **bufc_arg)
02398 {
02399     buff = buff_arg;
02400     bufc = bufc_arg;
02401     bNeedSpace = false;
02402 
02403     // Trim Spaces from beginning.
02404     //
02405     while (mux_isspace(*number))
02406     {
02407         number++;
02408     }
02409 
02410     if (*number == '-')
02411     {
02412         StartWord();
02413         AddWord("negative");
02414         number++;
02415     }
02416 
02417     // Trim Zeroes from Beginning.
02418     //
02419     while (*number == '0')
02420     {
02421         number++;
02422     }
02423 
02424     const char *pA = number;
02425     while (mux_isdigit(*number))
02426     {
02427         number++;
02428     }
02429     size_t nA = number - pA;
02430 
02431     const char *pB  = NULL;
02432     size_t nB = 0;
02433     if (*number == '.')
02434     {
02435         number++;
02436         pB = number;
02437         while (mux_isdigit(*number))
02438         {
02439             number++;
02440         }
02441         nB = number - pB;
02442     }
02443 
02444     // Skip trailing spaces.
02445     //
02446     while (mux_isspace(*number))
02447     {
02448         number++;
02449     }
02450 
02451     if (  *number
02452        || nA >= 16
02453        || nB >= 15)
02454     {
02455         safe_str("#-1 ARGUMENT MUST BE A NUMBER", buff, bufc);
02456         return;
02457     }
02458 
02459     if (nA == 0)
02460     {
02461         if (nB == 0)
02462         {
02463             StartWord();
02464             AddWord("zero");
02465         }
02466     }
02467     else
02468     {
02469         ManyDigits(nA, pA, true);
02470         if (nB)
02471         {
02472             StartWord();
02473             AddWord("and");
02474         }
02475     }
02476     if (nB)
02477     {
02478         FractionalDigits(nB, pB);
02479     }
02480 }
02481 
02482 FUNCTION(fun_spellnum)
02483 {
02484     UNUSED_PARAMETER(executor);
02485     UNUSED_PARAMETER(caller);
02486     UNUSED_PARAMETER(enactor);
02487     UNUSED_PARAMETER(nfargs);
02488     UNUSED_PARAMETER(cargs);
02489     UNUSED_PARAMETER(ncargs);
02490 
02491     CSpellNum sn;
02492     sn.SpellNum(fargs[0], buff, bufc);
02493 }
02494 
02495 FUNCTION(fun_roman)
02496 {
02497     UNUSED_PARAMETER(executor);
02498     UNUSED_PARAMETER(caller);
02499     UNUSED_PARAMETER(enactor);
02500     UNUSED_PARAMETER(nfargs);
02501     UNUSED_PARAMETER(cargs);
02502     UNUSED_PARAMETER(ncargs);
02503 
02504     const char *number = fargs[0];
02505 
02506     // Trim Spaces from beginning.
02507     //
02508     while (mux_isspace(*number))
02509     {
02510         number++;
02511     }
02512 
02513     // Trim Zeroes from Beginning.
02514     //
02515     while (*number == '0')
02516     {
02517         number++;
02518     }
02519 
02520     const char *pA = number;
02521     while (mux_isdigit(*number))
02522     {
02523         number++;
02524     }
02525     size_t nA = number - pA;
02526 
02527     // Skip trailing spaces.
02528     //
02529     while (mux_isspace(*number))
02530     {
02531         number++;
02532     }
02533 
02534     // Validate that argument is numeric with a value between 1 and 3999.
02535     //
02536     if (*number || nA < 1)
02537     {
02538         safe_str("#-1 ARGUMENT MUST BE A POSITIVE NUMBER", buff, bufc);
02539         return;
02540     }
02541     else if (  nA > 4
02542             || (  nA == 1
02543                && pA[0] == '0')
02544             || (  nA == 4
02545                && '3' < pA[0]))
02546     {
02547         safe_range(buff, bufc);
02548         return;
02549     }
02550 
02551     // I:1, V:5, X:10, L:50, C:100, D:500, M:1000
02552     //
02553     // Ones:      _ I II III IV V VI VII VIII IX
02554     // Tens:      _ X XX XXX XL L LX LXX LXXX XC
02555     // Hundreds:  _ C CC CCC CD D DC DCC DCCC CM
02556     // Thousands: _ M MM MMM
02557     //
02558     static const char aLetters[4][3] =
02559     {
02560         { 'I', 'V', 'X' },
02561         { 'X', 'L', 'C' },
02562         { 'C', 'D', 'M' },
02563         { 'M', ' ', ' ' }
02564     };
02565 
02566     static const char *aCode[10] =
02567     {
02568         "",
02569         "1",
02570         "11",
02571         "111",
02572         "12",
02573         "2",
02574         "21",
02575         "211",
02576         "2111",
02577         "13"
02578     };
02579 
02580     while (nA--)
02581     {
02582         const char *pCode = aCode[*pA - '0'];
02583         const char *pLetters = aLetters[nA];
02584 
02585         while (*pCode)
02586         {
02587             safe_chr(pLetters[*pCode - '1'], buff, bufc);
02588             pCode++;
02589         }
02590         pA++;
02591     }
02592 }
02593 
02594 /*-------------------------------------------------------------------------
02595  * List-based numeric functions.
02596  */
02597 
02598 FUNCTION(fun_land)
02599 {
02600     UNUSED_PARAMETER(executor);
02601     UNUSED_PARAMETER(caller);
02602     UNUSED_PARAMETER(enactor);
02603     UNUSED_PARAMETER(cargs);
02604     UNUSED_PARAMETER(ncargs);
02605 
02606     bool bValue = true;
02607     if (0 < nfargs)
02608     {
02609         SEP sep;
02610         if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
02611         {
02612             return;
02613         }
02614 
02615         char *cp = trim_space_sep(fargs[0], &sep);
02616         while (cp && bValue)
02617         {
02618             char *curr = split_token(&cp, &sep);
02619             bValue = isTRUE(mux_atol(curr));
02620         }
02621     }
02622     safe_bool(bValue, buff, bufc);
02623 }
02624 
02625 FUNCTION(fun_lor)
02626 {
02627     UNUSED_PARAMETER(executor);
02628     UNUSED_PARAMETER(caller);
02629     UNUSED_PARAMETER(enactor);
02630     UNUSED_PARAMETER(cargs);
02631     UNUSED_PARAMETER(ncargs);
02632 
02633     bool bValue = false;
02634     if (0 < nfargs)
02635     {
02636         SEP sep;
02637         if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
02638         {
02639             return;
02640         }
02641 
02642         char *cp = trim_space_sep(fargs[0], &sep);
02643         while (cp && !bValue)
02644         {
02645             char *curr = split_token(&cp, &sep);
02646             bValue = isTRUE(mux_atol(curr));
02647         }
02648     }
02649     safe_bool(bValue, buff, bufc);
02650 }
02651 
02652 FUNCTION(fun_band)
02653 {
02654     UNUSED_PARAMETER(executor);
02655     UNUSED_PARAMETER(caller);
02656     UNUSED_PARAMETER(enactor);
02657     UNUSED_PARAMETER(cargs);
02658     UNUSED_PARAMETER(ncargs);
02659 
02660     UINT64 val = UINT64_MAX_VALUE;
02661     for (int i = 0; i < nfargs; i++)
02662     {
02663         if (is_integer(fargs[i], NULL))
02664         {
02665             val &= mux_atoi64(fargs[i]);
02666         }
02667         else
02668         {
02669             safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
02670             return;
02671         }
02672     }
02673     safe_i64toa(val, buff, bufc);
02674 }
02675 
02676 FUNCTION(fun_bor)
02677 {
02678     UNUSED_PARAMETER(executor);
02679     UNUSED_PARAMETER(caller);
02680     UNUSED_PARAMETER(enactor);
02681     UNUSED_PARAMETER(cargs);
02682     UNUSED_PARAMETER(ncargs);
02683 
02684     UINT64 val = 0;
02685     for (int i = 0; i < nfargs; i++)
02686     {
02687         if (is_integer(fargs[i], NULL))
02688         {
02689             val |= mux_atoi64(fargs[i]);
02690         }
02691         else
02692         {
02693             safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
02694             return;
02695         }
02696     }
02697     safe_i64toa(val, buff, bufc);
02698 }
02699 
02700 FUNCTION(fun_bnand)
02701 {
02702     UNUSED_PARAMETER(executor);
02703     UNUSED_PARAMETER(caller);
02704     UNUSED_PARAMETER(enactor);
02705     UNUSED_PARAMETER(nfargs);
02706     UNUSED_PARAMETER(cargs);
02707     UNUSED_PARAMETER(ncargs);
02708 
02709     if (  is_integer(fargs[0], NULL)
02710        && is_integer(fargs[1], NULL))
02711     {
02712         INT64 a = mux_atoi64(fargs[0]);
02713         INT64 b = mux_atoi64(fargs[1]);
02714         safe_i64toa(a & ~(b), buff, bufc);
02715     }
02716     else
02717     {
02718         safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
02719     }
02720 }
02721 
02722 FUNCTION(fun_bxor)
02723 {
02724     UNUSED_PARAMETER(executor);
02725     UNUSED_PARAMETER(caller);
02726     UNUSED_PARAMETER(enactor);
02727     UNUSED_PARAMETER(cargs);
02728     UNUSED_PARAMETER(ncargs);
02729 
02730     UINT64 val = 0;
02731     for (int i = 0; i < nfargs; i++)
02732     {
02733         if (is_integer(fargs[i], NULL))
02734         {
02735             val ^= mux_atoi64(fargs[i]);
02736         }
02737         else
02738         {
02739             safe_str("#-1 ARGUMENTS MUST BE INTEGERS", buff, bufc);
02740             return;
02741         }
02742     }
02743     safe_i64toa(val, buff, bufc);
02744 }
02745 
02746 FUNCTION(fun_crc32)
02747 {
02748     UNUSED_PARAMETER(executor);
02749     UNUSED_PARAMETER(caller);
02750     UNUSED_PARAMETER(enactor);
02751     UNUSED_PARAMETER(cargs);
02752     UNUSED_PARAMETER(ncargs);
02753 
02754     UINT32 ulCRC32 = 0;
02755     for (int i = 0; i < nfargs; i++)
02756     {
02757         int n = strlen(fargs[i]);
02758         ulCRC32 = CRC32_ProcessBuffer(ulCRC32, fargs[i], n);
02759     }
02760     safe_i64toa(ulCRC32, buff, bufc);
02761 }
02762 
02763 FUNCTION(fun_sha1)
02764 {
02765     UNUSED_PARAMETER(executor);
02766     UNUSED_PARAMETER(caller);
02767     UNUSED_PARAMETER(enactor);
02768     UNUSED_PARAMETER(cargs);
02769     UNUSED_PARAMETER(ncargs);
02770 
02771     int i;
02772     SHA1_CONTEXT shac;
02773     SHA1_Init(&shac);
02774     for (i = 0; i < nfargs; i++)
02775     {
02776         SHA1_Compute(&shac, strlen(fargs[i]), fargs[i]);
02777     }
02778     SHA1_Final(&shac);
02779     for (i = 0; i <= 4; i++)
02780     {
02781         char buf[9];
02782         sprintf(buf, "%08X", shac.H[i]);
02783         safe_str(buf, buff, bufc);
02784     }
02785 }

Generated on Mon May 28 04:40:10 2007 for MUX by  doxygen 1.4.7