openenvutils/commandshell/shell/src/modules/mathfunc.c
changeset 0 2e3d3ce01487
child 1 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // mathfunc.c - basic mathematical functions for use in math evaluations
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1999 Peter Stephenson
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Peter Stephenson or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Peter Stephenson and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Peter Stephenson and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Peter Stephenson and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 #include "mathfunc.mdh"
       
    32 #include "mathfunc.pro"
       
    33 
       
    34 #include <math.h>
       
    35 
       
    36 #ifdef __SYMBIAN32__
       
    37 #ifdef __WINSCW__
       
    38 #pragma warn_unusedarg off
       
    39 #endif//__WINSCW__
       
    40 #endif//__SYMBIAN32__
       
    41 
       
    42 enum {
       
    43 MF_ABS,
       
    44 MF_ACOS,
       
    45 MF_ACOSH,
       
    46 MF_ASIN,
       
    47 MF_ASINH,
       
    48 MF_ATAN,
       
    49 MF_ATANH,
       
    50 MF_CBRT,
       
    51 MF_CEIL,
       
    52 MF_COPYSIGN,
       
    53 MF_COS,
       
    54 MF_COSH,
       
    55 MF_ERF,
       
    56 MF_ERFC,
       
    57 MF_EXP,
       
    58 MF_EXPM1,
       
    59 MF_FABS,
       
    60 MF_FLOAT,
       
    61 MF_FLOOR,
       
    62 MF_FMOD,
       
    63 MF_GAMMA,
       
    64 MF_HYPOT,
       
    65 MF_ILOGB,
       
    66 MF_INT,
       
    67 MF_J0,
       
    68 MF_J1,
       
    69 MF_JN,
       
    70 MF_LDEXP,
       
    71 MF_LGAMMA,
       
    72 MF_LOG,
       
    73 MF_LOG10,
       
    74 MF_LOG1P,
       
    75 MF_LOGB,
       
    76 MF_NEXTAFTER,
       
    77 MF_RINT,
       
    78 MF_SCALB,
       
    79 #ifdef HAVE_SIGNGAM
       
    80 MF_SIGNGAM,
       
    81 #endif
       
    82 MF_SIN,
       
    83 MF_SINH,
       
    84 MF_SQRT,
       
    85 MF_TAN,
       
    86 MF_TANH,
       
    87 MF_Y0,
       
    88 MF_Y1,
       
    89 MF_YN
       
    90 };
       
    91 
       
    92 /* also functions taking a string argument */
       
    93 
       
    94 enum {
       
    95 MS_RAND48
       
    96 };
       
    97 
       
    98 /*
       
    99  * also to do, but differently argument or returned: abs (no type
       
   100  * conversion), atan2.
       
   101  */
       
   102 
       
   103 /* Flags for bounds.  Note these must start at 1, not 0. */
       
   104 
       
   105 enum {
       
   106   BF_POS    = 1,		/* must be positive */
       
   107   BF_NONNEG = 2,		/* must be non-negative */
       
   108   BF_FRAC   = 3,		/* must be -1 <= x <= 1 */
       
   109   BF_GE1    = 4,		/* must be >= 1 */
       
   110   BF_FRACO  = 5,		/* must be in open range -1 < x < 1 */
       
   111   BF_INTPOS = 6,		/* must be non-integer or positive */
       
   112   BF_GTRM1  = 7,		/* must be > -1 */
       
   113   BF_NONZ   = 8,		/* must be nonzero */
       
   114   BF_POS2   = 9			/* second argument must be positive */
       
   115 };
       
   116 
       
   117 #define BFLAG(x) ((x) << 8)
       
   118 
       
   119 /*
       
   120  * Flags for type of function: unlike the above, these must
       
   121  * be individually bit-testable.
       
   122  */
       
   123 
       
   124 enum {
       
   125     TF_NOCONV = 1,		/* don't convert to float */
       
   126     TF_INT1   = 2,		/* first argument is integer */
       
   127     TF_INT2   = 4,		/* second argument is integer */
       
   128     TF_NOASS  = 8		/* don't assign result as double */
       
   129 };
       
   130 
       
   131 #define TFLAG(x) ((x) << 16)
       
   132 
       
   133 
       
   134 static struct mathfunc mftab[] = {
       
   135   /* Functions taking string arguments */
       
   136 #ifdef HAVE_ERAND48
       
   137   /* here to avoid comma hassle */
       
   138   STRMATHFUNC("rand48", math_string, MS_RAND48),
       
   139 #endif
       
   140 
       
   141   NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) |
       
   142 	      TFLAG(TF_NOCONV|TF_NOASS)),
       
   143   NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)),
       
   144   NUMMATHFUNC("acosh", math_func, 1, 1, MF_ACOSH | BFLAG(BF_GE1)),
       
   145   NUMMATHFUNC("asin", math_func, 1, 1, MF_ASIN | BFLAG(BF_FRAC)),
       
   146   NUMMATHFUNC("asinh", math_func, 1, 1, MF_ASINH),
       
   147   NUMMATHFUNC("atan", math_func, 1, 2, MF_ATAN),
       
   148   NUMMATHFUNC("atanh", math_func, 1, 1, MF_ATANH | BFLAG(BF_FRACO)),
       
   149   NUMMATHFUNC("cbrt", math_func, 1, 1, MF_CBRT),
       
   150   NUMMATHFUNC("ceil", math_func, 1, 1, MF_CEIL),
       
   151   NUMMATHFUNC("copysign", math_func, 2, 2, MF_COPYSIGN),
       
   152   NUMMATHFUNC("cos", math_func, 1, 1, MF_COS),
       
   153   NUMMATHFUNC("cosh", math_func, 1, 1, MF_COSH),
       
   154   NUMMATHFUNC("erf", math_func, 1, 1, MF_ERF),
       
   155   NUMMATHFUNC("erfc", math_func, 1, 1, MF_ERFC),
       
   156   NUMMATHFUNC("exp", math_func, 1, 1, MF_EXP),
       
   157   NUMMATHFUNC("expm1", math_func, 1, 1, MF_EXPM1),
       
   158   NUMMATHFUNC("fabs", math_func, 1, 1, MF_FABS),
       
   159   NUMMATHFUNC("float", math_func, 1, 1, MF_FLOAT),
       
   160   NUMMATHFUNC("floor", math_func, 1, 1, MF_FLOOR),
       
   161   NUMMATHFUNC("fmod", math_func, 2, 2, MF_FMOD),
       
   162   NUMMATHFUNC("gamma", math_func, 1, 1, MF_GAMMA | BFLAG(BF_INTPOS)),
       
   163   NUMMATHFUNC("hypot", math_func, 2, 2, MF_HYPOT),
       
   164   NUMMATHFUNC("ilogb", math_func, 1, 1, MF_ILOGB | BFLAG(BF_NONZ) |
       
   165 	      TFLAG(TF_NOASS)),
       
   166   NUMMATHFUNC("int", math_func, 1, 1, MF_INT | TFLAG(TF_NOASS)),
       
   167   NUMMATHFUNC("j0", math_func, 1, 1, MF_J0),
       
   168   NUMMATHFUNC("j1", math_func, 1, 1, MF_J1),
       
   169   NUMMATHFUNC("jn", math_func, 2, 2, MF_JN | TFLAG(TF_INT1)),
       
   170   NUMMATHFUNC("ldexp", math_func, 2, 2, MF_LDEXP | TFLAG(TF_INT2)),
       
   171   NUMMATHFUNC("lgamma", math_func, 1, 1, MF_LGAMMA | BFLAG(BF_INTPOS)),
       
   172   NUMMATHFUNC("log", math_func, 1, 1, MF_LOG | BFLAG(BF_POS)),
       
   173   NUMMATHFUNC("log10", math_func, 1, 1, MF_LOG10 | BFLAG(BF_POS)),
       
   174   NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P | BFLAG(BF_GTRM1)),
       
   175   NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB | BFLAG(BF_NONZ)),
       
   176   NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER),
       
   177   NUMMATHFUNC("rint", math_func, 1, 1, MF_RINT),
       
   178   NUMMATHFUNC("scalb", math_func, 2, 2, MF_SCALB | TFLAG(TF_INT2)),
       
   179 #ifdef HAVE_SIGNGAM
       
   180   NUMMATHFUNC("signgam", math_func, 0, 0, MF_SIGNGAM | TFLAG(TF_NOASS)),
       
   181 #endif
       
   182   NUMMATHFUNC("sin", math_func, 1, 1, MF_SIN),
       
   183   NUMMATHFUNC("sinh", math_func, 1, 1, MF_SINH),
       
   184   NUMMATHFUNC("sqrt", math_func, 1, 1, MF_SQRT | BFLAG(BF_NONNEG)),
       
   185   NUMMATHFUNC("tan", math_func, 1, 1, MF_TAN),
       
   186   NUMMATHFUNC("tanh", math_func, 1, 1, MF_TANH),
       
   187   NUMMATHFUNC("y0", math_func, 1, 1, MF_Y0 | BFLAG(BF_POS)),
       
   188   NUMMATHFUNC("y1", math_func, 1, 1, MF_Y1 | BFLAG(BF_POS)),
       
   189   NUMMATHFUNC("yn", math_func, 2, 2, MF_YN | BFLAG(BF_POS2) | TFLAG(TF_INT1))
       
   190 };
       
   191 
       
   192 /**/
       
   193 static mnumber
       
   194 math_func(char *name, int argc, mnumber *argv, int id)
       
   195 {
       
   196   mnumber ret;
       
   197 
       
   198   double argd = 0, argd2 = 0, retd = 0;
       
   199   int argi = 0;
       
   200 
       
   201   if (argc && !(id & TFLAG(TF_NOCONV))) {
       
   202       if (id & TFLAG(TF_INT1))
       
   203 	  argi = (argv->type == MN_FLOAT) ? (zlong)argv->u.d : argv->u.l;
       
   204       else
       
   205 	  argd = (argv->type == MN_INTEGER) ? (double)argv->u.l : argv->u.d;
       
   206       if (argc > 1) {
       
   207 	  if (id & TFLAG(TF_INT2))
       
   208 	      argi = (argv[1].type == MN_FLOAT) ? (zlong)argv[1].u.d :
       
   209 	      argv[1].u.l;
       
   210 	  else
       
   211 	      argd2 = (argv[1].type == MN_INTEGER) ? (double)argv[1].u.l :
       
   212 	      argv[1].u.d;
       
   213       }
       
   214   }
       
   215 
       
   216   ret.type = MN_FLOAT;
       
   217   ret.u.d = 0;
       
   218 
       
   219   if (errflag)
       
   220     return ret;
       
   221 
       
   222   if (id & 0xff00) {
       
   223       int rtst = 0;
       
   224 
       
   225       switch ((id >> 8) & 0xff) {
       
   226       case BF_POS:
       
   227 	  rtst = (argd <= 0.0);
       
   228 	  break;
       
   229 	  
       
   230       case BF_NONNEG:
       
   231 	  rtst = (argd < 0.0);
       
   232 	  break;
       
   233 
       
   234       case BF_FRAC:
       
   235 	  rtst = (fabs(argd) > 1.0);
       
   236 	  break;
       
   237 
       
   238       case BF_GE1:
       
   239 	  rtst = (argd < 1.0);
       
   240 	  break;
       
   241 
       
   242       case BF_FRACO:
       
   243 	  rtst = (fabs(argd) >= 1.0);
       
   244 	  break;
       
   245 
       
   246       case BF_INTPOS:
       
   247 	  rtst = (argd <= 0 && (double)(zlong)argd == argd);
       
   248 	  break;
       
   249 
       
   250       case BF_GTRM1:
       
   251 	  rtst = (argd <= -1);
       
   252 	  break;
       
   253 
       
   254       case BF_POS2:
       
   255 	  rtst = (argd2 <= 0.0);
       
   256 	  break;
       
   257       }
       
   258 
       
   259       if (rtst) {
       
   260 	  zerr("math: argument to %s out of range", name, 0);
       
   261 	  return ret;
       
   262       }
       
   263   }
       
   264 
       
   265   switch (id & 0xff) {
       
   266   case MF_ABS:
       
   267       ret.type = argv->type;
       
   268       if (argv->type == MN_INTEGER)
       
   269 	  ret.u.l = (argv->u.l < 0) ? - argv->u.l : argv->u.l;
       
   270       else
       
   271 	  ret.u.d = fabs(argv->u.d);
       
   272       break;
       
   273 
       
   274   case MF_ACOS:
       
   275     retd = acos(argd); 
       
   276       break;
       
   277 
       
   278   case MF_ACOSH:
       
   279     retd = acosh(argd);
       
   280       break;
       
   281 
       
   282   case MF_ASIN:
       
   283      retd = asin(argd);
       
   284       break;
       
   285 
       
   286   case MF_ASINH:
       
   287     retd = asinh(argd);
       
   288       break;
       
   289 
       
   290   case MF_ATAN:
       
   291       if (argc == 2)
       
   292 	  retd = atan2(argd, argd2);
       
   293       else
       
   294 	  retd = atan(argd);
       
   295       break;
       
   296 
       
   297   case MF_ATANH:
       
   298       retd = atanh(argd);
       
   299       break;
       
   300 
       
   301   case MF_CBRT:
       
   302       retd = cbrt(argd);
       
   303       break;
       
   304 
       
   305   case MF_CEIL:
       
   306       retd = ceil(argd);
       
   307       break;
       
   308 
       
   309   case MF_COPYSIGN:
       
   310       retd = copysign(argd, argd2);
       
   311       break;
       
   312 
       
   313   case MF_COS:
       
   314       retd = cos(argd);
       
   315       break;
       
   316 
       
   317   case MF_COSH:
       
   318       retd = cosh(argd);
       
   319       break;
       
   320 
       
   321   case MF_ERF:
       
   322       retd = erf(argd);
       
   323       break;
       
   324 
       
   325   case MF_ERFC:
       
   326       retd = erfc(argd);
       
   327       break;
       
   328 
       
   329   case MF_EXP:
       
   330       retd = exp(argd);
       
   331       break;
       
   332 
       
   333   case MF_EXPM1:
       
   334       retd = expm1(argd);
       
   335       break;
       
   336 
       
   337   case MF_FABS:
       
   338       retd = fabs(argd);
       
   339       break;
       
   340 
       
   341   case MF_FLOAT:
       
   342       retd = argd;
       
   343       break;
       
   344 
       
   345   case MF_FLOOR:
       
   346       retd = floor(argd);
       
   347       break;
       
   348 
       
   349   case MF_FMOD:
       
   350       retd = fmod(argd, argd2);
       
   351       break;
       
   352 
       
   353   case MF_GAMMA:
       
   354       retd = gamma(argd); 
       
   355       break;
       
   356 
       
   357   case MF_HYPOT:
       
   358       retd = hypot(argd, argd2);
       
   359       break;
       
   360 
       
   361   case MF_ILOGB:
       
   362       ret.type = MN_INTEGER;
       
   363       ret.u.l = ilogb(argd); 
       
   364       break;
       
   365 
       
   366   case MF_INT:
       
   367       ret.type = MN_INTEGER;
       
   368       ret.u.l = (zlong)argd;
       
   369       break;
       
   370 
       
   371   case MF_J0:
       
   372       retd = j0(argd);
       
   373       break;
       
   374 
       
   375   case MF_J1:
       
   376       retd = j1(argd);
       
   377       break;
       
   378 
       
   379   case MF_JN:
       
   380       retd = jn(argi, argd2); 
       
   381       break;
       
   382 
       
   383   case MF_LDEXP:
       
   384       retd = ldexp(argd, argi);
       
   385       break;
       
   386 
       
   387   case MF_LGAMMA:
       
   388       retd = lgamma(argd);
       
   389       break;
       
   390 
       
   391   case MF_LOG:
       
   392       retd = log(argd);
       
   393       break;
       
   394 
       
   395   case MF_LOG10:
       
   396       retd = log10(argd);
       
   397       break;
       
   398 
       
   399   case MF_LOG1P:
       
   400       retd = log1p(argd);
       
   401       break;
       
   402 
       
   403   case MF_LOGB:
       
   404       retd = logb(argd); 
       
   405       break;
       
   406 
       
   407   case MF_NEXTAFTER:
       
   408       retd = nextafter(argd, argd2);
       
   409       break;
       
   410 
       
   411   case MF_RINT:
       
   412       retd = rint(argd);
       
   413       break;
       
   414 
       
   415   case MF_SCALB:
       
   416       retd = scalb(argd, argi); 
       
   417       break;
       
   418 
       
   419 #ifdef HAVE_SIGNGAM
       
   420   case MF_SIGNGAM:
       
   421       ret.type = MN_INTEGER;
       
   422       ret.u.l = signgam; 
       
   423       break;
       
   424 #endif
       
   425 
       
   426   case MF_SIN:
       
   427       retd = sin(argd);
       
   428       break;
       
   429 
       
   430   case MF_SINH:
       
   431       retd = sinh(argd);
       
   432       break;
       
   433 
       
   434   case MF_SQRT:
       
   435       retd = sqrt(argd);
       
   436       break;
       
   437 
       
   438   case MF_TAN:
       
   439       retd = tan(argd);
       
   440       break;
       
   441 
       
   442   case MF_TANH:
       
   443       retd = tanh(argd);
       
   444       break;
       
   445 
       
   446   case MF_Y0:
       
   447       retd = y0(argd);
       
   448       break;
       
   449 
       
   450   case MF_Y1:
       
   451       retd = y1(argd); 
       
   452       break;
       
   453 
       
   454   case MF_YN:
       
   455       retd = yn(argi, argd2);
       
   456       break;
       
   457 
       
   458 #ifdef DEBUG
       
   459   default:
       
   460       fprintf(stderr, "BUG: mathfunc type not handled: %d", id);
       
   461       break;
       
   462 #endif
       
   463   }
       
   464 
       
   465   if (!(id & TFLAG(TF_NOASS)))
       
   466       ret.u.d = retd;
       
   467   return ret;
       
   468 }
       
   469 
       
   470 /**/
       
   471 static mnumber
       
   472 math_string(UNUSED(char *name), char *arg, int id)
       
   473 {
       
   474     mnumber ret = zero_mnumber;
       
   475     char *send;
       
   476     /*
       
   477      * Post-process the string argument, which is just passed verbatim.
       
   478      * Not clear if any other functions that use math_string() will
       
   479      * want this, but assume so for now.
       
   480      */
       
   481     while (iblank(*arg))
       
   482 	arg++;
       
   483     send = arg + strlen(arg);
       
   484     while (send > arg && iblank(send[-1]))
       
   485 	send--;
       
   486     *send = '\0';
       
   487 
       
   488     switch (id)
       
   489     {
       
   490 #ifdef HAVE_ERAND48
       
   491     case MS_RAND48:
       
   492 	{
       
   493 	    static unsigned short seedbuf[3];
       
   494 	    static int seedbuf_init;
       
   495 	    unsigned short tmp_seedbuf[3], *seedbufptr;
       
   496 	    int do_init = 1;
       
   497 
       
   498 	    if (*arg) {
       
   499 		/* Seed is contained in parameter named by arg */
       
   500 		char *seedstr;
       
   501 		seedbufptr = tmp_seedbuf;
       
   502 		if ((seedstr = getsparam(arg)) && strlen(seedstr) >= 12) {
       
   503 		    int i, j;
       
   504 		    do_init = 0;
       
   505 		    /*
       
   506 		     * Decode three sets of four hex digits corresponding
       
   507 		     * to each unsigned short.
       
   508 		     */
       
   509 		    for (i = 0; i < 3 && !do_init; i++) {
       
   510 			unsigned short *seedptr = seedbufptr + i;
       
   511 			*seedptr = 0;
       
   512 			for (j = 0; j < 4; j++) {
       
   513 			    if (*seedstr >= '0' && *seedstr <= '9')
       
   514 				*seedptr += *seedstr - '0';
       
   515 			    else if (tolower(*seedstr) >= 'a' &&
       
   516 				     tolower(*seedstr) <= 'f')
       
   517 				*seedptr += tolower(*seedstr) - 'a' + 10;
       
   518 			    else {
       
   519 				do_init = 1;
       
   520 				break;
       
   521 			    }
       
   522 			    seedstr++;
       
   523 			    if (j < 3)
       
   524 				*seedptr *= 16;
       
   525 			}
       
   526 		    }
       
   527 		}
       
   528 		else if (errflag)
       
   529 		    break;
       
   530 	    }
       
   531 	    else
       
   532 	    {
       
   533 		/* Use default seed: must be initialised. */
       
   534 		seedbufptr = seedbuf;
       
   535 		if (!seedbuf_init)
       
   536 		    seedbuf_init = 1;
       
   537 		else
       
   538 		    do_init = 1;
       
   539 	    }
       
   540 	    if (do_init) {
       
   541 		seedbufptr[0] = (unsigned short)rand();
       
   542 		seedbufptr[1] = (unsigned short)rand();
       
   543 		seedbufptr[2] = (unsigned short)rand();
       
   544 	    }
       
   545 	    ret.type = MN_FLOAT;
       
   546 	    ret.u.d = 0;//erand48(seedbufptr); //KARTHIK
       
   547 
       
   548 	    if (*arg)
       
   549 	    {
       
   550 		char outbuf[13];
       
   551 		sprintf(outbuf, "%04x%04x%04x", (int)seedbufptr[0],
       
   552 			(int)seedbufptr[1], (int)seedbufptr[2]);
       
   553 		setsparam(arg, ztrdup(outbuf));
       
   554 	    }
       
   555 	}
       
   556 	break;
       
   557 #endif
       
   558     }
       
   559 
       
   560     return ret;
       
   561 }
       
   562 
       
   563 
       
   564 /**/
       
   565 int
       
   566 setup_(UNUSED(Module m))
       
   567 {
       
   568     return 0;
       
   569 }
       
   570 
       
   571 /**/
       
   572 int
       
   573 boot_(Module m)
       
   574 {
       
   575     return !addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
       
   576 }
       
   577 
       
   578 /**/
       
   579 int
       
   580 cleanup_(Module m)
       
   581 {
       
   582     deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
       
   583     return 0;
       
   584 }
       
   585 
       
   586 /**/
       
   587 int
       
   588 finish_(UNUSED(Module m))
       
   589 {
       
   590     return 0;
       
   591 }