fltfmt.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*
  2. * The authors of this software are Rob Pike and Ken Thompson.
  3. * Copyright (c) 2002 by Lucent Technologies.
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose without fee is hereby granted, provided that this entire notice
  6. * is included in all copies of any software which is or includes a copy
  7. * or modification of this software and in all copies of the supporting
  8. * documentation for such software.
  9. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
  10. * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
  11. * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  12. * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  13. */
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <float.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <errno.h>
  20. #include <stdarg.h>
  21. #include "fmt.h"
  22. #include "fmtdef.h"
  23. #include "nan.h"
  24. enum
  25. {
  26. FDEFLT = 6,
  27. NSIGNIF = 17
  28. };
  29. /*
  30. * first few powers of 10, enough for about 1/2 of the
  31. * total space for doubles.
  32. */
  33. static double pows10[] =
  34. {
  35. 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
  36. 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
  37. 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
  38. 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
  39. 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
  40. 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
  41. 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
  42. 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
  43. 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
  44. 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
  45. 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
  46. 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
  47. 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
  48. 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
  49. 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
  50. 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
  51. };
  52. static double
  53. pow10(int n)
  54. {
  55. double d;
  56. int neg;
  57. neg = 0;
  58. if(n < 0){
  59. if(n < DBL_MIN_10_EXP){
  60. return 0.;
  61. }
  62. neg = 1;
  63. n = -n;
  64. }else if(n > DBL_MAX_10_EXP){
  65. return HUGE_VAL;
  66. }
  67. if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))
  68. d = pows10[n];
  69. else{
  70. d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
  71. for(;;){
  72. n -= sizeof(pows10)/sizeof(pows10[0]) - 1;
  73. if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){
  74. d *= pows10[n];
  75. break;
  76. }
  77. d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
  78. }
  79. }
  80. if(neg){
  81. return 1./d;
  82. }
  83. return d;
  84. }
  85. static int
  86. xadd(char *a, int n, int v)
  87. {
  88. char *b;
  89. int c;
  90. if(n < 0 || n >= NSIGNIF)
  91. return 0;
  92. for(b = a+n; b >= a; b--) {
  93. c = *b + v;
  94. if(c <= '9') {
  95. *b = c;
  96. return 0;
  97. }
  98. *b = '0';
  99. v = 1;
  100. }
  101. *a = '1'; /* overflow adding */
  102. return 1;
  103. }
  104. static int
  105. xsub(char *a, int n, int v)
  106. {
  107. char *b;
  108. int c;
  109. for(b = a+n; b >= a; b--) {
  110. c = *b - v;
  111. if(c >= '0') {
  112. *b = c;
  113. return 0;
  114. }
  115. *b = '9';
  116. v = 1;
  117. }
  118. *a = '9'; /* underflow subtracting */
  119. return 1;
  120. }
  121. static void
  122. xaddexp(char *p, int e)
  123. {
  124. char se[9];
  125. int i;
  126. *p++ = 'e';
  127. if(e < 0) {
  128. *p++ = '-';
  129. e = -e;
  130. }
  131. i = 0;
  132. while(e) {
  133. se[i++] = e % 10 + '0';
  134. e /= 10;
  135. }
  136. if(i == 0) {
  137. *p++ = '0';
  138. } else {
  139. while(i > 0)
  140. *p++ = se[--i];
  141. }
  142. *p++ = '\0';
  143. }
  144. static char*
  145. xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign)
  146. {
  147. char s2[NSIGNIF+10];
  148. double g, h;
  149. int e, d, i;
  150. int c2, sign, oerr;
  151. if(chr == 'F')
  152. chr = 'f';
  153. if(prec > NSIGNIF)
  154. prec = NSIGNIF;
  155. if(prec < 0)
  156. prec = 0;
  157. if(__isNaN(f)) {
  158. *decpt = 9999;
  159. *rsign = 0;
  160. strcpy(s1, "nan");
  161. return &s1[3];
  162. }
  163. sign = 0;
  164. if(f < 0) {
  165. f = -f;
  166. sign++;
  167. }
  168. *rsign = sign;
  169. if(__isInf(f, 1) || __isInf(f, -1)) {
  170. *decpt = 9999;
  171. strcpy(s1, "inf");
  172. return &s1[3];
  173. }
  174. e = 0;
  175. g = f;
  176. if(g != 0) {
  177. frexp(f, &e);
  178. e = (int)(e * .301029995664);
  179. if(e >= -150 && e <= +150) {
  180. d = 0;
  181. h = f;
  182. } else {
  183. d = e/2;
  184. h = f * pow10(-d);
  185. }
  186. g = h * pow10(d-e);
  187. while(g < 1) {
  188. e--;
  189. g = h * pow10(d-e);
  190. }
  191. while(g >= 10) {
  192. e++;
  193. g = h * pow10(d-e);
  194. }
  195. }
  196. /*
  197. * convert NSIGNIF digits and convert
  198. * back to get accuracy.
  199. */
  200. for(i=0; i<NSIGNIF; i++) {
  201. d = (int)g;
  202. s1[i] = d + '0';
  203. g = (g - d) * 10;
  204. }
  205. s1[i] = 0;
  206. /*
  207. * try decimal rounding to eliminate 9s
  208. */
  209. c2 = prec + 1;
  210. if(chr == 'f')
  211. c2 += e;
  212. oerr = errno;
  213. if(c2 >= NSIGNIF-2) {
  214. strcpy(s2, s1);
  215. d = e;
  216. s1[NSIGNIF-2] = '0';
  217. s1[NSIGNIF-1] = '0';
  218. xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
  219. g = fmtstrtod(s1, nil);
  220. if(g == f)
  221. goto found;
  222. if(xadd(s1, NSIGNIF-3, 1)) {
  223. e++;
  224. xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
  225. }
  226. g = fmtstrtod(s1, nil);
  227. if(g == f)
  228. goto found;
  229. strcpy(s1, s2);
  230. e = d;
  231. }
  232. /*
  233. * convert back so s1 gets exact answer
  234. */
  235. for(d = 0; d < 10; d++) {
  236. xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
  237. g = fmtstrtod(s1, nil);
  238. if(f > g) {
  239. if(xadd(s1, NSIGNIF-1, 1))
  240. e--;
  241. continue;
  242. }
  243. if(f < g) {
  244. if(xsub(s1, NSIGNIF-1, 1))
  245. e++;
  246. continue;
  247. }
  248. break;
  249. }
  250. found:
  251. errno = oerr;
  252. /*
  253. * sign
  254. */
  255. d = 0;
  256. i = 0;
  257. /*
  258. * round & adjust 'f' digits
  259. */
  260. c2 = prec + 1;
  261. if(chr == 'f'){
  262. if(xadd(s1, c2+e, 5))
  263. e++;
  264. c2 += e;
  265. if(c2 < 0){
  266. c2 = 0;
  267. e = -prec - 1;
  268. }
  269. }else{
  270. if(xadd(s1, c2, 5))
  271. e++;
  272. }
  273. if(c2 > NSIGNIF){
  274. c2 = NSIGNIF;
  275. }
  276. *decpt = e + 1;
  277. /*
  278. * terminate the converted digits
  279. */
  280. s1[c2] = '\0';
  281. return &s1[c2];
  282. }
  283. /*
  284. * this function works like the standard dtoa, if you want it.
  285. */
  286. #if 0
  287. static char*
  288. __dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve)
  289. {
  290. static char s2[NSIGNIF + 10];
  291. char *es;
  292. int chr, prec;
  293. switch(mode) {
  294. /* like 'e' */
  295. case 2:
  296. case 4:
  297. case 6:
  298. case 8:
  299. chr = 'e';
  300. break;
  301. /* like 'g' */
  302. case 0:
  303. case 1:
  304. default:
  305. chr = 'g';
  306. break;
  307. /* like 'f' */
  308. case 3:
  309. case 5:
  310. case 7:
  311. case 9:
  312. chr = 'f';
  313. break;
  314. }
  315. if(chr != 'f' && ndigits){
  316. ndigits--;
  317. }
  318. prec = ndigits;
  319. if(prec > NSIGNIF)
  320. prec = NSIGNIF;
  321. if(ndigits == 0)
  322. prec = NSIGNIF;
  323. es = xdodtoa(s2, f, chr, prec, decpt, rsign);
  324. /*
  325. * strip trailing 0
  326. */
  327. for(; es > s2 + 1; es--){
  328. if(es[-1] != '0'){
  329. break;
  330. }
  331. }
  332. *es = '\0';
  333. if(rve != NULL)
  334. *rve = es;
  335. return s2;
  336. }
  337. #endif
  338. static int
  339. fmtzdotpad(Fmt *f, int n, int pt)
  340. {
  341. char *t, *s;
  342. int i;
  343. Rune *rt, *rs;
  344. if(f->runes){
  345. rt = (Rune*)f->to;
  346. rs = (Rune*)f->stop;
  347. for(i = 0; i < n; i++){
  348. if(i == pt){
  349. FMTRCHAR(f, rt, rs, '.');
  350. }
  351. FMTRCHAR(f, rt, rs, '0');
  352. }
  353. f->nfmt += rt - (Rune*)f->to;
  354. f->to = rt;
  355. }else{
  356. t = (char*)f->to;
  357. s = (char*)f->stop;
  358. for(i = 0; i < n; i++){
  359. if(i == pt){
  360. FMTCHAR(f, t, s, '.');
  361. }
  362. FMTCHAR(f, t, s, '0');
  363. }
  364. f->nfmt += t - (char *)f->to;
  365. f->to = t;
  366. }
  367. return 0;
  368. }
  369. int
  370. __efgfmt(Fmt *fmt)
  371. {
  372. double f;
  373. char s1[NSIGNIF+10];
  374. int e, d, n;
  375. int c1, c2, c3, c4, ucase, sign, chr, prec, fl;
  376. f = va_arg(fmt->args, double);
  377. prec = FDEFLT;
  378. fl = fmt->flags;
  379. fmt->flags = 0;
  380. if(fl & FmtPrec)
  381. prec = fmt->prec;
  382. chr = fmt->r;
  383. ucase = 0;
  384. if(chr == 'E'){
  385. chr = 'e';
  386. ucase = 1;
  387. }else if(chr == 'F'){
  388. chr = 'f';
  389. ucase = 1;
  390. }else if(chr == 'G'){
  391. chr = 'g';
  392. ucase = 1;
  393. }
  394. if(prec > 0 && chr == 'g')
  395. prec--;
  396. if(prec < 0)
  397. prec = 0;
  398. xdodtoa(s1, f, chr, prec, &e, &sign);
  399. e--;
  400. if(*s1 == 'i' || *s1 == 'n'){
  401. if(ucase){
  402. if(*s1 == 'i'){
  403. strcpy(s1, "INF");
  404. }else{
  405. strcpy(s1, "NAN");
  406. }
  407. }
  408. fmt->flags = fl & (FmtWidth|FmtLeft);
  409. return __fmtcpy(fmt, (const void*)s1, 3, 3);
  410. }
  411. /*
  412. * copy into final place
  413. * c1 digits of leading '0'
  414. * c2 digits from conversion
  415. * c3 digits of trailing '0'
  416. * c4 digits after '.'
  417. */
  418. c1 = 0;
  419. c2 = prec + 1;
  420. c3 = 0;
  421. c4 = prec;
  422. switch(chr) {
  423. default:
  424. chr = 'e';
  425. break;
  426. case 'g':
  427. /*
  428. * decide on 'e' of 'f' style convers
  429. */
  430. if(e >= -4 && e <= prec) {
  431. c1 = -e;
  432. c4 = prec - e;
  433. chr = 'h'; /* flag for 'f' style */
  434. }
  435. break;
  436. case 'f':
  437. c1 = -e;
  438. if(c1 > prec)
  439. c1 = prec + 1;
  440. c2 += e;
  441. break;
  442. }
  443. /*
  444. * clean up c1 c2 and c3
  445. */
  446. if(c1 < 0)
  447. c1 = 0;
  448. if(c2 < 0)
  449. c2 = 0;
  450. if(c2 > NSIGNIF) {
  451. c3 = c2-NSIGNIF;
  452. c2 = NSIGNIF;
  453. }
  454. /*
  455. * trim trailing zeros for %g
  456. */
  457. if(!(fl & FmtSharp)
  458. && (chr == 'g' || chr == 'h')){
  459. if(c4 >= c3){
  460. c4 -= c3;
  461. c3 = 0;
  462. }else{
  463. c3 -= c4;
  464. c4 = 0;
  465. }
  466. while(c4 && c2 > 1 && s1[c2 - 1] == '0'){
  467. c4--;
  468. c2--;
  469. }
  470. }
  471. /*
  472. * calculate the total length
  473. */
  474. n = c1 + c2 + c3;
  475. if(sign || (fl & (FmtSign|FmtSpace)))
  476. n++;
  477. if(c4 || (fl & FmtSharp)){
  478. n++;
  479. }
  480. if(chr == 'e' || chr == 'g'){
  481. n += 4;
  482. if(e >= 100)
  483. n++;
  484. }
  485. /*
  486. * pad to width if right justified
  487. */
  488. if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){
  489. if(fl & FmtZero){
  490. c1 += fmt->width - n;
  491. }else{
  492. if(__fmtpad(fmt, fmt->width - n) < 0){
  493. return -1;
  494. }
  495. }
  496. }
  497. /*
  498. * sign
  499. */
  500. d = 0;
  501. if(sign)
  502. d = '-';
  503. else if(fl & FmtSign)
  504. d = '+';
  505. else if(fl & FmtSpace)
  506. d = ' ';
  507. if(d && fmtrune(fmt, d) < 0){
  508. return -1;
  509. }
  510. /*
  511. * copy digits
  512. */
  513. c4 = c1 + c2 + c3 - c4;
  514. if(c1 > 0){
  515. if(fmtzdotpad(fmt, c1, c4) < 0){
  516. return -1;
  517. }
  518. c4 -= c1;
  519. }
  520. d = 0;
  521. if(c4 >= 0 && c4 < c2){
  522. if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)
  523. return -1;
  524. d = c4;
  525. c2 -= c4;
  526. c4 = -1;
  527. }
  528. if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){
  529. return -1;
  530. }
  531. c4 -= c2;
  532. if(c3 > 0){
  533. if(fmtzdotpad(fmt, c3, c4) < 0){
  534. return -1;
  535. }
  536. c4 -= c3;
  537. }
  538. /*
  539. * strip trailing '0' on g conv
  540. */
  541. if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){
  542. return -1;
  543. }
  544. if(chr == 'e' || chr == 'g') {
  545. d = 0;
  546. if(ucase)
  547. s1[d++] = 'E';
  548. else
  549. s1[d++] = 'e';
  550. c1 = e;
  551. if(c1 < 0) {
  552. s1[d++] = '-';
  553. c1 = -c1;
  554. } else
  555. s1[d++] = '+';
  556. if(c1 >= 100) {
  557. s1[d++] = c1/100 + '0';
  558. c1 = c1%100;
  559. }
  560. s1[d++] = c1/10 + '0';
  561. s1[d++] = c1%10 + '0';
  562. if(__fmtcpy(fmt, s1, d, d) < 0){
  563. return -1;
  564. }
  565. }
  566. if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){
  567. if(__fmtpad(fmt, fmt->width - n) < 0){
  568. return -1;
  569. }
  570. }
  571. return 0;
  572. }