Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
  2. #include <stdlib.h>
  3. #include <ctype.h>
  4. #include <libc/unconst.h>
  5.  
  6. static long double powten[] =
  7. {
  8.   1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
  9.   1e512L, 1e1024L, 1e2048L, 1e4096L
  10. };
  11.  
  12. long double
  13. _strtold(const char *s, char **sret)
  14. {
  15.   long double r;                /* result */
  16.   int e, ne;                    /* exponent */
  17.   int sign;                     /* +- 1.0 */
  18.   int esign;
  19.   int flags=0;
  20.   int l2powm1;
  21.  
  22.   r = 0.0L;
  23.   sign = 1;
  24.   e = ne = 0;
  25.   esign = 1;
  26.  
  27.   while(*s && isspace(*s))
  28.     s++;
  29.  
  30.   if (*s == '+')
  31.     s++;
  32.   else if (*s == '-')
  33.   {
  34.     sign = -1;
  35.     s++;
  36.   }
  37.  
  38.   while ((*s >= '0') && (*s <= '9'))
  39.   {
  40.     flags |= 1;
  41.     r *= 10.0L;
  42.     r += *s - '0';
  43.     s++;
  44.   }
  45.  
  46.   if (*s == '.')
  47.   {
  48.     s++;
  49.     while ((*s >= '0') && (*s <= '9'))
  50.     {
  51.       flags |= 2;
  52.       r *= 10.0L;
  53.       r += *s - '0';
  54.       s++;
  55.       ne++;
  56.     }
  57.   }
  58.   if (flags == 0)
  59.   {
  60.     if (sret)
  61.       *sret = unconst(s, char *);
  62.     return 0.0L;
  63.   }
  64.  
  65.   if ((*s == 'e') || (*s == 'E'))
  66.   {
  67.     s++;
  68.     if (*s == '+')
  69.       s++;
  70.     else if (*s == '-')
  71.     {
  72.       s++;
  73.       esign = -1;
  74.     }
  75.     while ((*s >= '0') && (*s <= '9'))
  76.     {
  77.       e *= 10;
  78.       e += *s - '0';
  79.       s++;
  80.     }
  81.   }
  82.   if (esign < 0)
  83.   {
  84.     esign = -esign;
  85.     e = -e;
  86.   }
  87.   e = e - ne;
  88.   if (e < -4096)
  89.   {
  90.     /* possibly subnormal number, 10^e would overflow */
  91.     r *= 1.0e-2048L;
  92.     e += 2048;
  93.   }
  94.   if (e < 0)
  95.   {
  96.     e = -e;
  97.     esign = -esign;
  98.   }
  99.   if (e >= 8192)
  100.     e = 8191;
  101.   if (e)
  102.   {
  103.     long double d = 1.0L;
  104.     l2powm1 = 0;
  105.     while (e)
  106.     {
  107.       if (e & 1)
  108.         d *= powten[l2powm1];
  109.       e >>= 1;
  110.       l2powm1++;
  111.     }
  112.     if (esign > 0)
  113.       r *= d;
  114.     else
  115.       r /= d;
  116.   }
  117.   if (sret)
  118.     *sret = unconst(s, char *);
  119.   return r * sign;
  120. }
  121.