~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to strings/dtoa.c

  • Committer: Monty Taylor
  • Date: 2008-07-05 18:10:38 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705181038-0ih0nnamu5qrut0y
Fixed prototypes. Cleaned define a little bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 
36
36
 ***************************************************************/
37
37
 
 
38
#include <my_base.h> /* for EOVERFLOW on Windows */
 
39
#include <my_global.h>
38
40
#include <m_string.h>  /* for memcpy and NOT_FIXED_DEC */
39
41
 
40
42
/**
77
79
                      (including the terminating '\0').
78
80
   @param error       if not NULL, points to a location where the status of
79
81
                      conversion is stored upon return.
80
 
                      false  successful conversion
81
 
                      true   the input number is [-,+]infinity or nan.
 
82
                      FALSE  successful conversion
 
83
                      TRUE   the input number is [-,+]infinity or nan.
82
84
                             The output string in this case is always '0'.
83
85
   @return            number of written characters (excluding terminating '\0')
84
86
*/
85
87
 
86
 
size_t my_fcvt(double x, int precision, char *to, bool *error)
 
88
size_t my_fcvt(double x, int precision, char *to, my_bool *error)
87
89
{
88
90
  int decpt, sign, len, i;
89
91
  char *res, *src, *end, *dst= to;
90
92
  char buf[DTOA_BUFF_SIZE];
91
 
  assert(precision >= 0 && precision < NOT_FIXED_DEC && to != NULL);
 
93
  DBUG_ASSERT(precision >= 0 && precision < NOT_FIXED_DEC && to != NULL);
92
94
  
93
95
  res= dtoa(x, 5, precision, &decpt, &sign, &end, buf, sizeof(buf));
94
96
 
98
100
    *to++= '0';
99
101
    *to= '\0';
100
102
    if (error != NULL)
101
 
      *error= true;
 
103
      *error= TRUE;
102
104
    return 1;
103
105
  }
104
106
 
130
132
    if (len <= decpt)
131
133
      *dst++= '.';
132
134
    
133
 
    for (i= precision - cmax(0, (len - decpt)); i > 0; i--)
 
135
    for (i= precision - max(0, (len - decpt)); i > 0; i--)
134
136
      *dst++= '0';
135
137
  }
136
138
  
137
139
  *dst= '\0';
138
140
  if (error != NULL)
139
 
    *error= false;
 
141
    *error= FALSE;
140
142
 
141
143
  dtoa_free(res, buf, sizeof(buf));
142
144
 
179
181
                      'width + 1' bytes.
180
182
   @param error       if not NULL, points to a location where the status of
181
183
                      conversion is stored upon return.
182
 
                      false  successful conversion
183
 
                      true   the input number is [-,+]infinity or nan.
 
184
                      FALSE  successful conversion
 
185
                      TRUE   the input number is [-,+]infinity or nan.
184
186
                             The output string in this case is always '0'.
185
187
   @return            number of written characters (excluding terminating '\0')
186
188
 
207
209
*/
208
210
 
209
211
size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
210
 
               bool *error)
 
212
               my_bool *error)
211
213
{
212
214
  int decpt, sign, len, exp_len;
213
215
  char *res, *src, *end, *dst= to, *dend= dst + width;
214
216
  char buf[DTOA_BUFF_SIZE];
215
 
  bool have_space, force_e_format;
216
 
  assert(width > 0 && to != NULL);
 
217
  my_bool have_space, force_e_format;
 
218
  DBUG_ASSERT(width > 0 && to != NULL);
217
219
  
218
220
  /* We want to remove '-' from equations early */
219
221
  if (x < 0.)
220
222
    width--;
221
223
 
222
 
  res= dtoa(x, 4, type == MY_GCVT_ARG_DOUBLE ? width : cmin(width, FLT_DIG),
 
224
  res= dtoa(x, 4, type == MY_GCVT_ARG_DOUBLE ? width : min(width, FLT_DIG),
223
225
            &decpt, &sign, &end, buf, sizeof(buf));
224
226
  if (decpt == DTOA_OVERFLOW)
225
227
  {
227
229
    *to++= '0';
228
230
    *to= '\0';
229
231
    if (error != NULL)
230
 
      *error= true;
 
232
      *error= TRUE;
231
233
    return 1;
232
234
  }
233
235
 
234
236
  if (error != NULL)
235
 
    *error= false;
 
237
    *error= FALSE;
236
238
 
237
239
  src= res;
238
240
  len= end - res;
315
317
      if (width < decpt)
316
318
      {
317
319
        if (error != NULL)
318
 
          *error= true;
 
320
          *error= TRUE;
319
321
        width= decpt;
320
322
      }
321
323
      
382
384
    {
383
385
      /* Overflow */
384
386
      if (error != NULL)
385
 
        *error= true;
 
387
        *error= TRUE;
386
388
      width= 0;
387
389
    }
388
390
      
459
461
{
460
462
  char buf[DTOA_BUFF_SIZE];
461
463
  double res;
462
 
  assert(str != NULL && end != NULL && *end != NULL && error != NULL);
 
464
  DBUG_ASSERT(str != NULL && end != NULL && *end != NULL && error != NULL);
463
465
 
464
466
  res= my_strtod_int(str, end, error, buf, sizeof(buf));
465
467
  return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX);
528
530
  file.
529
531
*/
530
532
 
531
 
typedef int32_t Long;
532
 
typedef uint32_t ULong;
533
 
typedef int64_t LLong;
534
 
typedef uint64_t ULLong;
 
533
/*
 
534
  #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
 
535
       and dtoa should round accordingly.
 
536
  #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
 
537
       and Honor_FLT_ROUNDS is not #defined.
 
538
 
 
539
  TODO: check if we can get rid of the above two
 
540
*/
 
541
 
 
542
typedef int32 Long;
 
543
typedef uint32 ULong;
 
544
typedef int64 LLong;
 
545
typedef uint64 ULLong;
535
546
 
536
547
typedef union { double d; ULong L[2]; } U;
537
548
 
583
594
#endif
584
595
#endif /*Flt_Rounds*/
585
596
 
 
597
#ifdef Honor_FLT_ROUNDS
 
598
#define Rounding rounding
 
599
#undef Check_FLT_ROUNDS
 
600
#define Check_FLT_ROUNDS
 
601
#else
 
602
#define Rounding Flt_Rounds
 
603
#endif
 
604
 
586
605
#define rounded_product(a,b) a*= b
587
606
#define rounded_quotient(a,b) a/= b
588
607
 
594
613
 
595
614
#define Kmax 15
596
615
 
597
 
#define Bcopy(x,y) memcpy(&x->sign, &y->sign, \
 
616
#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign,   \
598
617
                          2*sizeof(int) + y->wds*sizeof(ULong))
599
618
 
600
619
/* Arbitrary-length integer */
1310
1329
  double aadj, aadj1, adj, rv, rv0;
1311
1330
  Long L;
1312
1331
  ULong y, z;
1313
 
  Bigint *bb= NULL, *bb1= NULL, *bd= NULL, *bd0= NULL, *bs= NULL, *delta= NULL;
 
1332
  Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1314
1333
#ifdef SET_INEXACT
1315
1334
  int inexact, oldinexact;
1316
1335
#endif
 
1336
#ifdef Honor_FLT_ROUNDS
 
1337
  int rounding;
 
1338
#endif
1317
1339
  Stack_alloc alloc;
1318
1340
 
1319
 
  c= 0;
1320
1341
  *error= 0;
1321
1342
 
1322
1343
  alloc.begin= alloc.free= buf;
1471
1492
  }
1472
1493
  bd0= 0;
1473
1494
  if (nd <= DBL_DIG
 
1495
#ifndef Honor_FLT_ROUNDS
 
1496
    && Flt_Rounds == 1
 
1497
#endif
1474
1498
      )
1475
1499
  {
1476
1500
    if (!e)
1479
1503
    {
1480
1504
      if (e <= Ten_pmax)
1481
1505
      {
 
1506
#ifdef Honor_FLT_ROUNDS
 
1507
        /* round correctly FLT_ROUNDS = 2 or 3 */
 
1508
        if (sign)
 
1509
        {
 
1510
          rv= -rv;
 
1511
          sign= 0;
 
1512
        }
 
1513
#endif
1482
1514
        /* rv = */ rounded_product(dval(rv), tens[e]);
1483
1515
        goto ret;
1484
1516
      }
1489
1521
          A fancier test would sometimes let us do
1490
1522
          this for larger i values.
1491
1523
        */
 
1524
#ifdef Honor_FLT_ROUNDS
 
1525
        /* round correctly FLT_ROUNDS = 2 or 3 */
 
1526
        if (sign)
 
1527
        {
 
1528
          rv= -rv;
 
1529
          sign= 0;
 
1530
        }
 
1531
#endif
1492
1532
        e-= i;
1493
1533
        dval(rv)*= tens[i];
1494
1534
        /* rv = */ rounded_product(dval(rv), tens[e]);
1498
1538
#ifndef Inaccurate_Divide
1499
1539
    else if (e >= -Ten_pmax)
1500
1540
    {
 
1541
#ifdef Honor_FLT_ROUNDS
 
1542
      /* round correctly FLT_ROUNDS = 2 or 3 */
 
1543
      if (sign)
 
1544
      {
 
1545
        rv= -rv;
 
1546
        sign= 0;
 
1547
      }
 
1548
#endif
1501
1549
      /* rv = */ rounded_quotient(dval(rv), tens[-e]);
1502
1550
      goto ret;
1503
1551
    }
1511
1559
    oldinexact= get_inexact();
1512
1560
#endif
1513
1561
  scale= 0;
 
1562
#ifdef Honor_FLT_ROUNDS
 
1563
  if ((rounding= Flt_Rounds) >= 2)
 
1564
  {
 
1565
    if (sign)
 
1566
      rounding= rounding == 2 ? 0 : 2;
 
1567
    else
 
1568
      if (rounding != 2)
 
1569
        rounding= 0;
 
1570
  }
 
1571
#endif
1514
1572
 
1515
1573
  /* Get starting approximation = rv * 10**e1 */
1516
1574
 
1525
1583
 ovfl:
1526
1584
        *error= EOVERFLOW;
1527
1585
        /* Can't trust HUGE_VAL */
 
1586
#ifdef Honor_FLT_ROUNDS
 
1587
        switch (rounding)
 
1588
        {
 
1589
        case 0: /* toward 0 */
 
1590
        case 3: /* toward -infinity */
 
1591
          word0(rv)= Big0;
 
1592
          word1(rv)= Big1;
 
1593
          break;
 
1594
        default:
 
1595
          word0(rv)= Exp_mask;
 
1596
          word1(rv)= 0;
 
1597
        }
 
1598
#else /*Honor_FLT_ROUNDS*/
1528
1599
        word0(rv)= Exp_mask;
1529
1600
        word1(rv)= 0;
 
1601
#endif /*Honor_FLT_ROUNDS*/
1530
1602
#ifdef SET_INEXACT
1531
1603
        /* set overflow bit */
1532
1604
        dval(rv0)= 1e300;
1622
1694
    else
1623
1695
      bd2-= bbe;
1624
1696
    bs2= bb2;
 
1697
#ifdef Honor_FLT_ROUNDS
 
1698
    if (rounding != 1)
 
1699
      bs2++;
 
1700
#endif
1625
1701
    j= bbe - scale;
1626
1702
    i= j + bbbits - 1;  /* logb(rv) */
1627
1703
    if (i < Emin)  /* denormal */
1659
1735
    dsign= delta->sign;
1660
1736
    delta->sign= 0;
1661
1737
    i= cmp(delta, bs);
 
1738
#ifdef Honor_FLT_ROUNDS
 
1739
    if (rounding != 1)
 
1740
    {
 
1741
      if (i < 0)
 
1742
      {
 
1743
        /* Error is less than an ulp */
 
1744
        if (!delta->x[0] && delta->wds <= 1)
 
1745
        {
 
1746
          /* exact */
 
1747
#ifdef SET_INEXACT
 
1748
          inexact= 0;
 
1749
#endif
 
1750
          break;
 
1751
        }
 
1752
        if (rounding)
 
1753
        {
 
1754
          if (dsign)
 
1755
          {
 
1756
            adj= 1.;
 
1757
            goto apply_adj;
 
1758
          }
 
1759
        }
 
1760
        else if (!dsign)
 
1761
        {
 
1762
          adj= -1.;
 
1763
          if (!word1(rv) && !(word0(rv) & Frac_mask))
 
1764
          {
 
1765
            y= word0(rv) & Exp_mask;
 
1766
            if (!scale || y > 2*P*Exp_msk1)
 
1767
            {
 
1768
              delta= lshift(delta,Log2P);
 
1769
              if (cmp(delta, bs) <= 0)
 
1770
              adj= -0.5;
 
1771
            }
 
1772
          }
 
1773
 apply_adj:
 
1774
          if (scale && (y= word0(rv) & Exp_mask) <= 2 * P * Exp_msk1)
 
1775
            word0(adj)+= (2 * P + 1) * Exp_msk1 - y;
 
1776
          dval(rv)+= adj * ulp(dval(rv));
 
1777
        }
 
1778
        break;
 
1779
      }
 
1780
      adj= ratio(delta, bs);
 
1781
      if (adj < 1.)
 
1782
        adj= 1.;
 
1783
      if (adj <= 0x7ffffffe)
 
1784
      {
 
1785
        /* adj = rounding ? ceil(adj) : floor(adj); */
 
1786
        y= adj;
 
1787
        if (y != adj)
 
1788
        {
 
1789
          if (!((rounding >> 1) ^ dsign))
 
1790
            y++;
 
1791
          adj= y;
 
1792
        }
 
1793
      }
 
1794
      if (scale && (y= word0(rv) & Exp_mask) <= 2 * P * Exp_msk1)
 
1795
        word0(adj)+= (2 * P + 1) * Exp_msk1 - y;
 
1796
      adj*= ulp(dval(rv));
 
1797
      if (dsign)
 
1798
        dval(rv)+= adj;
 
1799
      else
 
1800
        dval(rv)-= adj;
 
1801
      goto cont;
 
1802
    }
 
1803
#endif /*Honor_FLT_ROUNDS*/
1662
1804
 
1663
1805
    if (i < 0)
1664
1806
    {
1765
1907
    {
1766
1908
      aadj*= 0.5;
1767
1909
      aadj1= dsign ? aadj : -aadj;
 
1910
#ifdef Check_FLT_ROUNDS
 
1911
      switch (Rounding)
 
1912
      {
 
1913
      case 2: /* towards +infinity */
 
1914
        aadj1-= 0.5;
 
1915
        break;
 
1916
      case 0: /* towards 0 */
 
1917
      case 3: /* towards -infinity */
 
1918
        aadj1+= 0.5;
 
1919
      }
 
1920
#else
1768
1921
      if (Flt_Rounds == 0)
1769
1922
        aadj1+= 0.5;
 
1923
#endif /*Check_FLT_ROUNDS*/
1770
1924
    }
1771
1925
    y= word0(rv) & Exp_mask;
1772
1926
 
1983
2137
          1 ==> like 0, but with Steele & White stopping rule;
1984
2138
                e.g. with IEEE P754 arithmetic , mode 0 gives
1985
2139
                1e23 whereas mode 1 gives 9.999999999999999e22.
1986
 
          2 ==> cmax(1,ndigits) significant digits.  This gives a
 
2140
          2 ==> max(1,ndigits) significant digits.  This gives a
1987
2141
                return value similar to that of ecvt, except
1988
2142
                that trailing zeros are suppressed.
1989
2143
          3 ==> through ndigits past the decimal point.  This
1993
2147
          4,5 ==> similar to 2 and 3, respectively, but (in
1994
2148
                round-nearest mode) with the tests of mode 0 to
1995
2149
                possibly return a shorter string that rounds to d.
 
2150
                With IEEE arithmetic and compilation with
 
2151
                -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
 
2152
                as modes 2 and 3 when FLT_ROUNDS != 1.
1996
2153
          6-9 ==> Debugging modes similar to mode - 4:  don't try
1997
2154
                fast floating-point estimate (if applicable).
1998
2155
 
2002
2159
    to hold the suppressed trailing zeros.
2003
2160
  */
2004
2161
 
2005
 
  int bbits, b2, b5, be, dig, i, ieps, ilim=0, ilim0, ilim1= 0,
 
2162
  int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1= 0,
2006
2163
    j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
2007
2164
    spec_case, try_quick;
2008
2165
  Long L;
2009
2166
  int denorm;
2010
2167
  ULong x;
2011
 
  Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
 
2168
  Bigint *b, *b1, *delta, *mlo, *mhi, *S;
2012
2169
  double d2, ds, eps;
2013
2170
  char *s, *s0;
 
2171
#ifdef Honor_FLT_ROUNDS
 
2172
  int rounding;
 
2173
#endif
2014
2174
  Stack_alloc alloc;
2015
2175
  
2016
2176
  alloc.begin= alloc.free= buf;
2039
2199
    return res;
2040
2200
  }
2041
2201
  
 
2202
#ifdef Honor_FLT_ROUNDS
 
2203
  if ((rounding= Flt_Rounds) >= 2)
 
2204
  {
 
2205
    if (*sign)
 
2206
      rounding= rounding == 2 ? 0 : 2;
 
2207
    else
 
2208
      if (rounding != 2)
 
2209
        rounding= 0;
 
2210
  }
 
2211
#endif
2042
2212
 
2043
2213
  b= d2b(dval(d), &be, &bbits, &alloc);
2044
2214
  if ((i= (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))))
2122
2292
  if (mode < 0 || mode > 9)
2123
2293
    mode= 0;
2124
2294
 
 
2295
#ifdef Check_FLT_ROUNDS
 
2296
  try_quick= Rounding == 1;
 
2297
#else
2125
2298
  try_quick= 1;
 
2299
#endif
2126
2300
 
2127
2301
  if (mode > 5)
2128
2302
  {
2157
2331
  }
2158
2332
  s= s0= dtoa_alloc(i, &alloc);
2159
2333
 
 
2334
#ifdef Honor_FLT_ROUNDS
 
2335
  if (mode > 1 && rounding != 1)
 
2336
    leftright= 0;
 
2337
#endif
 
2338
 
2160
2339
  if (ilim >= 0 && ilim <= Quick_max && try_quick)
2161
2340
  {
2162
2341
    /* Try to get by with floating-point arithmetic. */
2286
2465
    {
2287
2466
      L= (Long)(dval(d) / ds);
2288
2467
      dval(d)-= L*ds;
 
2468
#ifdef Check_FLT_ROUNDS
 
2469
      /* If FLT_ROUNDS == 2, L will usually be high by 1 */
 
2470
      if (dval(d) < 0)
 
2471
      {
 
2472
        L--;
 
2473
        dval(d)+= ds;
 
2474
      }
 
2475
#endif
2289
2476
      *s++= '0' + (int)L;
2290
2477
      if (!dval(d))
2291
2478
      {
2293
2480
      }
2294
2481
      if (i == ilim)
2295
2482
      {
 
2483
#ifdef Honor_FLT_ROUNDS
 
2484
        if (mode > 1)
 
2485
        {
 
2486
          switch (rounding) {
 
2487
          case 0: goto ret1;
 
2488
          case 2: goto bump_up;
 
2489
          }
 
2490
        }
 
2491
#endif
2296
2492
        dval(d)+= dval(d);
2297
2493
        if (dval(d) > ds || (dval(d) == ds && L & 1))
2298
2494
        {
2354
2550
 
2355
2551
  spec_case= 0;
2356
2552
  if ((mode < 2 || leftright)
 
2553
#ifdef Honor_FLT_ROUNDS
 
2554
      && rounding == 1
 
2555
#endif
2357
2556
     )
2358
2557
  {
2359
2558
    if (!word1(d) && !(word0(d) & Bndry_mask) &&
2447
2646
      j1= delta->sign ? 1 : cmp(b, delta);
2448
2647
      Bfree(delta, &alloc);
2449
2648
      if (j1 == 0 && mode != 1 && !(word1(d) & 1)
 
2649
#ifdef Honor_FLT_ROUNDS
 
2650
          && rounding >= 1
 
2651
#endif
2450
2652
         )
2451
2653
      {
2452
2654
        if (dig == '9')
2462
2664
        {
2463
2665
          goto accept_dig;
2464
2666
        }
 
2667
#ifdef Honor_FLT_ROUNDS
 
2668
        if (mode > 1)
 
2669
          switch (rounding) {
 
2670
          case 0: goto accept_dig;
 
2671
          case 2: goto keep_dig;
 
2672
          }
 
2673
#endif /*Honor_FLT_ROUNDS*/
2465
2674
        if (j1 > 0)
2466
2675
        {
2467
2676
          b= lshift(b, 1, &alloc);
2476
2685
      }
2477
2686
      if (j1 > 0)
2478
2687
      {
 
2688
#ifdef Honor_FLT_ROUNDS
 
2689
        if (!rounding)
 
2690
          goto accept_dig;
 
2691
#endif
2479
2692
        if (dig == '9')
2480
2693
        { /* possible if i == 1 */
2481
2694
round_9_up:
2485
2698
        *s++= dig + 1;
2486
2699
        goto ret;
2487
2700
      }
 
2701
#ifdef Honor_FLT_ROUNDS
 
2702
keep_dig:
 
2703
#endif
2488
2704
      *s++= dig;
2489
2705
      if (i == ilim)
2490
2706
        break;
2513
2729
 
2514
2730
  /* Round off last digit */
2515
2731
 
 
2732
#ifdef Honor_FLT_ROUNDS
 
2733
  switch (rounding) {
 
2734
  case 0: goto trimzeros;
 
2735
  case 2: goto roundoff;
 
2736
  }
 
2737
#endif
2516
2738
  b= lshift(b, 1, &alloc);
2517
2739
  j= cmp(b, S);
2518
2740
  if (j > 0 || (j == 0 && dig & 1))
2529
2751
  }
2530
2752
  else
2531
2753
  {
 
2754
#ifdef Honor_FLT_ROUNDS
 
2755
trimzeros:
 
2756
#endif
2532
2757
    while (*--s == '0');
2533
2758
    s++;
2534
2759
  }