mpatof.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "cc.h"
  2. enum
  3. {
  4. Mpscale = 29, /* safely smaller than bits in a long */
  5. Mpprec = 36, /* Mpscale*Mpprec sb > largest fp exp */
  6. Mpbase = 1L<<Mpscale,
  7. };
  8. typedef
  9. struct
  10. {
  11. long a[Mpprec];
  12. char ovf;
  13. } Mp;
  14. int mpatof(char*, double*);
  15. int mpatov(char *s, vlong *v);
  16. void mpint(Mp*, int);
  17. void mppow(Mp*, int, int);
  18. void mpmul(Mp*, int);
  19. void mpadd(Mp*, Mp*);
  20. int mptof(Mp*, double*);
  21. /*
  22. * convert a string, s, to floating in *d
  23. * return conversion overflow.
  24. * required syntax is [+-]d*[.]d*[e[+-]d*]
  25. */
  26. int
  27. mpatof(char *s, double *d)
  28. {
  29. Mp a, b;
  30. int dp, c, f, ef, ex, zer;
  31. double d1, d2;
  32. dp = 0; /* digits after decimal point */
  33. f = 0; /* sign */
  34. ex = 0; /* exponent */
  35. zer = 1; /* zero */
  36. memset(&a, 0, sizeof(a));
  37. for(;;) {
  38. switch(c = *s++) {
  39. default:
  40. goto bad;
  41. case '-':
  42. f = 1;
  43. case ' ':
  44. case '\t':
  45. case '+':
  46. continue;
  47. case '.':
  48. dp = 1;
  49. continue;
  50. case '1':
  51. case '2':
  52. case '3':
  53. case '4':
  54. case '5':
  55. case '6':
  56. case '7':
  57. case '8':
  58. case '9':
  59. zer = 0;
  60. case '0':
  61. mpint(&b, c-'0');
  62. mpmul(&a, 10);
  63. mpadd(&a, &b);
  64. if(dp)
  65. dp++;
  66. continue;
  67. case 'E':
  68. case 'e':
  69. ex = 0;
  70. ef = 0;
  71. for(;;) {
  72. c = *s++;
  73. if(c == '+' || c == ' ' || c == '\t')
  74. continue;
  75. if(c == '-') {
  76. ef = 1;
  77. continue;
  78. }
  79. if(c >= '0' && c <= '9') {
  80. ex = ex*10 + (c-'0');
  81. continue;
  82. }
  83. break;
  84. }
  85. if(ef)
  86. ex = -ex;
  87. case 0:
  88. break;
  89. }
  90. break;
  91. }
  92. if(a.ovf)
  93. goto bad;
  94. if(zer) {
  95. *d = 0;
  96. return 0;
  97. }
  98. if(dp)
  99. dp--;
  100. dp -= ex;
  101. if(dp > 0) {
  102. /*
  103. * must divide by 10**dp
  104. */
  105. if(mptof(&a, &d1))
  106. goto bad;
  107. /*
  108. * trial exponent of 8**dp
  109. * 8 (being between 5 and 10)
  110. * should pick up all underflows
  111. * in the division of 5**dp.
  112. */
  113. d2 = frexp(d1, &ex);
  114. d2 = ldexp(d2, ex-3*dp);
  115. if(d2 == 0)
  116. goto bad;
  117. /*
  118. * decompose each 10 into 5*2.
  119. * create 5**dp in fixed point
  120. * and then play with the exponent
  121. * for the remaining 2**dp.
  122. * note that 5**dp will overflow
  123. * with as few as 134 input digits.
  124. */
  125. mpint(&a, 1);
  126. mppow(&a, 5, dp);
  127. if(mptof(&a, &d2))
  128. goto bad;
  129. d1 = frexp(d1/d2, &ex);
  130. d1 = ldexp(d1, ex-dp);
  131. if(d1 == 0)
  132. goto bad;
  133. } else {
  134. /*
  135. * must multiply by 10**|dp| --
  136. * just do it in fixed point.
  137. */
  138. mppow(&a, 10, -dp);
  139. if(mptof(&a, &d1))
  140. goto bad;
  141. }
  142. if(f)
  143. d1 = -d1;
  144. *d = d1;
  145. return 0;
  146. bad:
  147. return 1;
  148. }
  149. /*
  150. * convert a to floating in *d
  151. * return conversion overflow
  152. */
  153. int
  154. mptof(Mp *a, double *d)
  155. {
  156. double f, g;
  157. long x, *a1;
  158. int i;
  159. if(a->ovf)
  160. return 1;
  161. a1 = a->a;
  162. f = ldexp(*a1++, 0);
  163. for(i=Mpscale; i<Mpprec*Mpscale; i+=Mpscale)
  164. if(x = *a1++) {
  165. g = ldexp(x, i);
  166. /*
  167. * NOTE: the test (g==0) is plan9
  168. * specific. ansi compliant overflow
  169. * is signaled by HUGE and errno==ERANGE.
  170. * change this for your particular ldexp.
  171. */
  172. if(g == 0)
  173. return 1;
  174. f += g; /* this could bomb! */
  175. }
  176. *d = f;
  177. return 0;
  178. }
  179. /*
  180. * return a += b
  181. */
  182. void
  183. mpadd(Mp *a, Mp *b)
  184. {
  185. int i, c;
  186. long x, *a1, *b1;
  187. if(b->ovf)
  188. a->ovf = 1;
  189. if(a->ovf)
  190. return;
  191. c = 0;
  192. a1 = a->a;
  193. b1 = b->a;
  194. for(i=0; i<Mpprec; i++) {
  195. x = *a1 + *b1++ + c;
  196. c = 0;
  197. if(x >= Mpbase) {
  198. x -= Mpbase;
  199. c = 1;
  200. }
  201. *a1++ = x;
  202. }
  203. a->ovf = c;
  204. }
  205. /*
  206. * return a = c
  207. */
  208. void
  209. mpint(Mp *a, int c)
  210. {
  211. memset(a, 0, sizeof(*a));
  212. a->a[0] = c;
  213. }
  214. /*
  215. * return a *= c
  216. */
  217. void
  218. mpmul(Mp *a, int c)
  219. {
  220. Mp p;
  221. int b;
  222. memmove(&p, a, sizeof(p));
  223. if(!(c & 1))
  224. memset(a, 0, sizeof(*a));
  225. c &= ~1;
  226. for(b=2; c; b<<=1) {
  227. mpadd(&p, &p);
  228. if(c & b) {
  229. mpadd(a, &p);
  230. c &= ~b;
  231. }
  232. }
  233. }
  234. /*
  235. * return a *= b**e
  236. */
  237. void
  238. mppow(Mp *a, int b, int e)
  239. {
  240. int b1;
  241. b1 = b*b;
  242. b1 = b1*b1;
  243. while(e >= 4) {
  244. mpmul(a, b1);
  245. e -= 4;
  246. if(a->ovf)
  247. return;
  248. }
  249. while(e > 0) {
  250. mpmul(a, b);
  251. e--;
  252. }
  253. }