home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / dp / dp.lha / dp_val.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-18  |  4.0 KB  |  206 lines

  1. /* Three functions which extract a double-precision numeric value 
  2.    from a string.
  3.    
  4.    -- void dp_val(double *,char *) --
  5.  
  6.    Since Sozobon C doesn't support doubles, we use an array of
  7.    2 long values instead.
  8.  
  9.    Converts a string into a double-precision floating point value. 
  10.  
  11.    The string must contain a number of the following format:
  12.  
  13.     [+|-][.]nnn[.nnn][e|E[+|-]nnn]
  14.  
  15.     eg:     1234
  16.         12.25
  17.         -.12
  18.         1.5e+10    
  19.  
  20.    In other words, any legal AmigaBASIC integer or single-precision literal.
  21.  
  22.    This source was based upon code for VAL (see dates prior to October 1996).
  23.  
  24.    -------------------------------
  25.    Author: David J Benn
  26.      Date: 19th,24th January 1993,
  27.        14th,16th February 1993,
  28.        23rd January 1994,
  29.        5th June 1994,
  30.        17th,18th October 1996
  31.    -------------------------------
  32. */
  33.  
  34. #define BOOL     short
  35. #define BYTE     char
  36.  
  37. #define TRUE     (1L)
  38. #define FALSE     (0L)
  39. #define EOS    '\0'
  40.  
  41. /* global variables */
  42. char     ch;    
  43. long    cc;
  44.  
  45. /* IEEE DP math library bases */
  46. extern    long     MathIeeeDoubBaseBase;
  47. extern    long     MathIeeeDoubTransBase;
  48.  
  49. /* IEEE DP math functions */
  50. void    dp_longint_to_double();
  51. void    dp_add();
  52. void    dp_div();
  53. void    dp_mul();
  54. void    dp_pow();
  55.  
  56. /* functions */
  57. void nextch(str)
  58. char *str;
  59. {
  60.  /* retrieve next character from string. */
  61.  
  62.     ch = str[cc++];
  63. }
  64.  
  65. void dp_val(doubleval,str)
  66. long    doubleval[2];
  67. char     *str;
  68. {
  69. long     i;
  70. long     n[2];
  71. long     index;
  72. long     periods;
  73. long    placecount;
  74. long     places;
  75. long    ex;
  76. long     ex_sign;
  77. BOOL    period;
  78. long     sign;
  79. long    a[2],b[2],c[2],d[2],e[2];
  80.  
  81.   /* zero double value */
  82.   doubleval[0] = doubleval[1] = 0;
  83.  
  84.   /* start of string */
  85.   cc=0;
  86.  
  87.   /* convert str to double */
  88.   nextch(str);
  89.   while (ch <= ' ' && ch != EOS) nextch(str);  /* skip leading whitespace */
  90.  
  91.   /* + | - */
  92.   switch(ch)
  93.   {
  94.    case '-' :     sign = -1; nextch(str); 
  95.         break;
  96.   
  97.    case '+' :    sign = 1; nextch(str);
  98.         break;
  99.  
  100.    default  :    sign = 1; 
  101.   }
  102.  
  103.   if ((ch >= '0' && ch <= '9') || ch == '.')
  104.   {
  105.    n[0]=n[1]=0;
  106.    index=0;
  107.    period=FALSE;
  108.    periods=0;
  109.    placecount=0;
  110.    
  111.    /* is first char '.'? */
  112.    if (ch == '.')
  113.    {
  114.     period=TRUE;
  115.     placecount=0;
  116.     index=1;
  117.     periods++;
  118.    }
  119.  
  120.    /* get the value */
  121.    if (!period) n[0]=10*n[0]+(ch-'0');
  122.  
  123.    do
  124.    {
  125.     nextch(str);
  126.     if (ch >= '0' && ch <= '9') n[index]=10*n[index]+(ch-'0');
  127.     if ((ch >= '0' && ch <= '9') && period) placecount++;
  128.     if (ch == '.') periods++;
  129.     if ((ch == '.') && (!period))
  130.     {
  131.      period=TRUE;
  132.      placecount=0;
  133.      index=1;
  134.     }
  135.    }
  136.    while (((ch >= '0' && ch <= '9') || ch == '.') && (periods <= 1));
  137.  
  138.    /* integer or real? */
  139.    if (period && periods == 1)
  140.    {
  141.     /* make DP */
  142.     places=1;
  143.     for (i=1;i<=placecount;i++) places *= 10;
  144.  
  145.     /* integer component */
  146.     dp_longint_to_double(a,n[0]);
  147.  
  148.     /* fractional component */    
  149.     dp_longint_to_double(b,n[1]);
  150.     dp_longint_to_double(c,places);
  151.     dp_div(d,b,c);
  152.  
  153.     /* DP value */
  154.     dp_add(doubleval,a,d);
  155.    }  
  156.    else 
  157.       dp_longint_to_double(doubleval,n[0]);
  158.  
  159.    /* is it a real in exponential form? */
  160.    if (ch == 'E' || ch == 'e')
  161.    {
  162.     ex=0;
  163.     ex_sign=1;
  164.  
  165.     nextch(str);
  166.  
  167.     if (ch == '+') { ex_sign=1; nextch(str); }
  168.     else
  169.     if (ch == '-') { ex_sign=-1; nextch(str); }
  170.     
  171.     /* expected a digit so just return 0 */ 
  172.     if (ch < '0' || ch > '9') { doubleval[0] = doubleval[1] = 0; return; }
  173.  
  174.     /* get digits */
  175.     while (ch >= '0' && ch <= '9') { ex = 10*ex+(ch-'0'); nextch(str); }
  176.     ex *= ex_sign;
  177.  
  178.     /* convert to DP */
  179.     if (ex >= -308 && ex <= 307)    /* IEEE DP exponent limits as per RKM: Libraries */
  180.     {
  181.      /* if exponent is zero then doubleval=doubleval*1 since 10^0 = 1 */
  182.      if (ex != 0) 
  183.      {
  184.      /* n * 10^ex */
  185.      dp_longint_to_double(a,10);
  186.      dp_longint_to_double(b,ex);
  187.      dp_pow(c,a,b);
  188.      dp_mul(d,c,doubleval);
  189.      doubleval[0] = d[0]; doubleval[1] = d[1]; 
  190.      }
  191.     }
  192.     else
  193.      doubleval[0] = doubleval[1] = 0;
  194.    }
  195.   }
  196.   else
  197.     doubleval[0] = doubleval[1] = 0;
  198.  
  199.   /* positive or negative? */
  200.   if (sign == -1)
  201.   {
  202.     dp_neg(b,doubleval);
  203.       doubleval[0] = b[0]; doubleval[1] = b[1];
  204.   }
  205.