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