home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Contrib / Math / Source / MyMath.c < prev    next >
C/C++ Source or Header  |  2003-09-15  |  9KB  |  353 lines

  1. #include <windows.h>
  2. #include "Mathcrt.h"
  3. #include "MyMath.h"
  4. #include "Math.h"
  5.  
  6. // Converts String to Int (Dec, Hex) or Float value
  7. void StringToItem(char *&s, ExpressionItem *item, int options)
  8. {
  9.   item->type = IT_CONST | ITC_INT;
  10.   __int64 &v=*((__int64*)&(item->param1));
  11.   v = 0;
  12.  
  13.   // Check for right input
  14.   if (!s) return;
  15.  
  16.   // String-value
  17.   if ((((options & (STI_FLOAT | STI_INT)) == 0) || *s == '\'' || *s == '\"' || *s == '`' || 
  18.       ((*s != '+') && (*s != '-') && ((*s < '0') || (*s > '9'))))
  19.       && (options & STI_STRING))
  20.   {
  21.       // end of string char
  22.       char eol = 0;
  23.       if (*s == '\'' || *s == '\"' || *s == '`') eol = *s;
  24.       else s--;
  25.  
  26.       item->type = IT_CONST | ITC_STRING;
  27.       // allocate memory buffer for string
  28.       char *sp;
  29.       sp = *((char**)&(item->param1)) = AllocString();
  30.       while (*(++s) && (*s != eol))
  31.       {
  32.         *(sp++) = *s;
  33.       }
  34.       if (*s == eol) s++;
  35.       *sp = 0;
  36.   } else
  37.   {
  38.       // strip leading spaces and tabs
  39.       while ((*s == ' ') || (*s == '\t')) s++;
  40.   // Hex-value
  41.   if ((options & STI_INT) && *s == '0' && (s[1] == 'x' || s[1] == 'X'))
  42.   {
  43.     s++;
  44.     while (*(s+1) == '0') *s++;
  45.     for (;;)
  46.     {
  47.       int c=*(++s);
  48.       if (c >= '0' && c <= '9') c-='0';
  49.       else if (c >= 'a' && c <= 'f') c-='a'-10;
  50.       else if (c >= 'A' && c <= 'F') c-='A'-10;
  51.       else break;
  52.       v<<=4;
  53.       v+=c;
  54.     }
  55.   }
  56.   // Dec-value, possible floating-point
  57.   else
  58.   {
  59.     int sign=0, numsignif = 0;
  60.     if (*s == '-') sign++; else s--;
  61.     while (*(s+1) == '0') *s++;
  62.     for (;;)
  63.     {
  64.       int c=*(++s) - '0'; numsignif++;
  65.       if ((options & STI_FLOAT) && 
  66.           ((c == ('e'-'0')) || (c==('E'-'0')) || (c==('.'-'0'))
  67.           || (numsignif > 18)))
  68.       {
  69.           // Switch to floating point conversion rountine
  70.           item->type = IT_CONST | ITC_FLOAT;
  71.           double& d = *((double*)&(item->param1));
  72.           d = (double) v;
  73.  
  74.           while ((c >= 0) && (c <= 9))
  75.           {
  76.               d = d*10.0 + (double) c;
  77.               c=*(++s) - '0';
  78.           }
  79.  
  80.           // sub-decimal part
  81.           if (c == ('.'-'0'))
  82.           {
  83.             double pwr = 1.0, dec = 0.0;
  84.             for (;;)
  85.             {
  86.               c=*(++s) - '0';
  87.               if ((c < 0) || (c > 9)) break;
  88.               dec = dec*10.0 + (double) c;
  89.               pwr *= 10.0;
  90.             }
  91.             d += dec/pwr;
  92.           }
  93.           // exponental part
  94.           if ((c == ('E'-'0')) || (c == ('e'-'0')))
  95.           {
  96.               int expc = 0, esign = 0;
  97.               s++;
  98.               // detect exponential sign
  99.               if ((*s == '+') || (*s == '-')) 
  100.                   esign = (*s == '-');
  101.               else s--;
  102.  
  103.               // detect exp value
  104.               for (;;)
  105.               {
  106.                 c=*(++s) - '0';
  107.                 if ((c < 0) || (c > 9)) break;
  108.                 expc = expc*10 + c;
  109.               }
  110.  
  111.               if (expc >= DBL_MAX_EXP)
  112.               {
  113.                   d = HUGE_VAL;
  114.                   expc = 0;
  115.               }
  116.  
  117.               double pwr = 1;
  118.               while (expc > 99) { pwr *= 1.0e100; expc -= 100; }
  119.               while (expc > 9) { pwr *= 1.0e10; expc -= 10; }
  120.               while (expc) { pwr *= 10.0; expc--; }
  121.               if (esign) d /= pwr;
  122.               else d *= pwr;
  123.           }
  124.           if (sign) d = -d;
  125.           return;
  126.       }
  127.       if (c < 0 || c > 9) break;
  128.       v*=10;
  129.       v+=c;
  130.     }
  131.     if (sign) v = -v;
  132.     if ((options & STI_FLOAT) && ((options & STI_INT) == 0))
  133.     {
  134.         double& d = *((double*)&(item->param1));
  135.         d = (double) v;    
  136.         item->type = IT_CONST | ITC_FLOAT;
  137.     }
  138.   }
  139.   }
  140. }
  141.  
  142. void ItemToString(char *sbuf, ExpressionItem *item)
  143. {
  144.     if ((item == NULL) || ((item->type & ITEMTYPE) != IT_CONST))
  145.     {
  146.         *sbuf = 0;
  147.         return;
  148.     }
  149.  
  150.     switch (item->type & ITEMSUBTYPE) 
  151.     {
  152.     case ITC_STRING:
  153.         {
  154.         char *ptr = *((char**)&(item->param1));
  155.         while (*(sbuf++) = *(ptr++));
  156.         }
  157.         break;
  158.     case ITC_ARRAY:
  159.         {            
  160.             ArrayDesc *ad = (ArrayDesc *) item->param1;
  161.             for (int index = 0; index < ad->count; index++)
  162.                 if ((ad->array[index]) && 
  163.                     ((ad->array[index]->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST | ITC_INT)))
  164.                     if ((*(sbuf++) = (char) *((__int64*)&(ad->array[index]->param1))) == 0)
  165.                         break;
  166.         }
  167.         break;
  168.     case ITC_FLOAT:
  169.         FloatFormat(sbuf, *((double*)&(item->param1)), 6);
  170.         break;
  171.     case ITC_INT:
  172.         itoa64(*((__int64*)&(item->param1)), sbuf);
  173.         break;
  174.     }
  175. }
  176.  
  177. void itoa64(__int64 i, char *buffer)
  178. {
  179.     char buf[128], *b = buf;
  180.  
  181.     if (i < 0)
  182.     {
  183.         *(buffer++) = '-';
  184.         i = -i;
  185.     }
  186.     if (i == 0) *(buffer++) = '0';
  187.     else 
  188.     {
  189.         while (i > 0) 
  190.         {
  191.             *(b++) = '0' + ((char) (i%10));
  192.             i /= 10;
  193.         }
  194.         while (b > buf) *(buffer++) = *(--b);
  195.     }
  196.     *buffer = 0;
  197. }
  198.  
  199. #define _FLOAT_ROUND_ADJUST (double)5e-15
  200. extern "C"
  201.     int _floatp10(double *fnum, int *fsign, int prec);
  202. extern "C"
  203.     int _ftol(double num);
  204.  
  205. #define POS_INFINITY  "#INF"
  206. #define NEG_INFINITY "-#INF"
  207.  
  208. void FloatFormatF(char *s, double value, int prec)
  209. {
  210.     int fpower, fsign, fdigit, fprec = 0, fzfill = 0;
  211.  
  212.     fpower = _floatp10(&value, &fsign, prec);
  213.     if(fsign < 0) *s++ = '-';
  214.     if(fpower < 0)
  215.     {
  216.         *s++ = '0';
  217.         fpower++;
  218.         fzfill++;
  219.     } else {
  220.         while(fpower >= 0)
  221.         {
  222.            if(fprec < 16)
  223.            {
  224.                 fdigit = (int)value;
  225.                 *s++ = (char)((char)fdigit + (char)48);
  226.                 value -= (double)fdigit;
  227.                 value *= (double)10;
  228.                 value += _FLOAT_ROUND_ADJUST;
  229.                 fprec++;
  230.            } else {
  231.                 *s++ = '0';
  232.            }
  233.            fpower--;
  234.         }
  235.         fpower = 0;
  236.     }
  237.     if(prec)
  238.     {
  239.             *s++ = '.';
  240.             while(prec)
  241.             {
  242.               if(fzfill && fpower < 0)
  243.               {
  244.                 *s++ = '0';
  245.                 fpower++;
  246.               } else {
  247.                 if(fprec < 16)
  248.                 {
  249.                   fdigit = (int)value;
  250.                   *s++ = (unsigned char)((unsigned char)fdigit +
  251.                                          (unsigned char)48);
  252.  
  253.                   value -= (double)fdigit;
  254.                   value *= (double)10;
  255.                   value += _FLOAT_ROUND_ADJUST;
  256.                   fprec++;
  257.                 } else {
  258.                   *s++ = '0';
  259.                 }
  260.               }
  261.               prec--;
  262.             }
  263.     }
  264.     *s = '\0';
  265. }
  266.  
  267. void FloatFormatE(char *s, double fnum, int options)
  268. {
  269.     int fpower, fsign, fdigit, fprec = 0, prec, fzfill = 0;
  270.     double sfnum;
  271.  
  272.     prec = options & 0xF;
  273.  
  274.     sfnum = fnum;
  275.     fpower = _floatp10(&sfnum, &fsign, -999);
  276.     fpower = _floatp10(&fnum, &fsign, prec - fpower);
  277.     if(fsign < 0) *s++ = '-';
  278.     fdigit = (int)fnum;
  279.     *s++ = (char)((char)fdigit + (char)48);
  280.     fnum -= (double)fdigit;
  281.     fnum *= (double)10;
  282.     fnum += _FLOAT_ROUND_ADJUST;
  283.     if(prec)
  284.     {
  285.         *s++ = '.';
  286.         while(prec)
  287.         {
  288.             if(fprec < 16)
  289.             {
  290.                 fdigit = (int)fnum;
  291.                 *s++ = (unsigned char)((unsigned char)fdigit +
  292.                     (unsigned char)48);
  293.                 fnum -= (double)fdigit;
  294.                 fnum *= (double)10;
  295.                 fnum += _FLOAT_ROUND_ADJUST;
  296.                 fprec++;
  297.             } else *s++ = '0';
  298.             prec--;
  299.         }
  300.     }
  301.     *s++ = ((options & FF_LEXP)?('E'):('e'));
  302.     if(fpower >= 0)
  303.     {
  304.         *s++ = '+';
  305.     } else {
  306.         *s++ = '-';
  307.         fpower = -fpower;
  308.     }
  309.     if(fpower < 10) *s++ = '0';
  310.     itoa64(fpower, s);
  311. }
  312.  
  313. void FloatFormat(char *s, double value, int options)
  314. {
  315.     int prec = options & 0xF;
  316.  
  317.     if(value == HUGE_VAL)
  318.     {
  319.         lstrcpy(s, POS_INFINITY);
  320.         return;
  321.     } else if(value == -HUGE_VAL) {
  322.         lstrcpy(s, NEG_INFINITY);
  323.         return;
  324.     }
  325.  
  326.     if (options & FF_NOEXP) FloatFormatF(s, value, prec);
  327.     else
  328.     if (options & FF_EXP) FloatFormatE(s, value, options);
  329.     else
  330.     {
  331.         double sfnum = value;
  332.         int fsign, fpower;
  333.         fpower = _floatp10(&sfnum, &fsign, -999);
  334.         sfnum = value;
  335.         fpower = _floatp10(&sfnum, &fsign, prec - fpower);
  336.  
  337.         if((value != 0.0) && ((fpower < -4) || (fpower >= prec)))
  338.             FloatFormatE(s, value, options);
  339.         else 
  340.         {
  341.             prec -= (fpower + 1);
  342.             if(prec <= 0) prec = 1;
  343.             FloatFormatF(s, value, prec);
  344.         }        
  345.     }
  346. }
  347.  
  348. int lstrcmpn(char *s1, const char *s2, int chars)
  349. {
  350.     while ((chars > 0) && (*s1) && (*s2) && (*(s1) == *(s2))) chars--, s1++, s2++;
  351.     if ((chars == 0) || (*s1 == *s2)) return 0;
  352.     return (*s1 - *s2);
  353. }