~mysql/mysql-server/mysql-6.0

« back to all changes in this revision

Viewing changes to mit-pthreads/stdlib/strtod.c

  • Committer: bk at mysql
  • Date: 2000-07-31 19:29:14 UTC
  • Revision ID: sp1r-bk@work.mysql.com-20000731192914-08846
Import changeset

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** An alternative implemtation of "strtod()" that is both
 
3
** simplier, and thread-safe.
 
4
*/
 
5
#include <pthread.h>
 
6
#include <ctype.h>
 
7
#include <math.h>
 
8
 
 
9
#ifdef TEST
 
10
#  define strtod NewStrtod
 
11
#include <stdio.h>
 
12
#endif
 
13
 
 
14
static double scaler10[] = {
 
15
  1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
 
16
};
 
17
static double scaler1[] = {
 
18
  1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
 
19
};
 
20
static double pastpoint[] = {
 
21
  1e-1,  1e-2,  1e-3,  1e-4,  1e-5,  1e-6,  1e-7,  1e-8,  1e-9,
 
22
  1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18,  1e-19,
 
23
  1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28,  1e-29,
 
24
  1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38,  1e-39,
 
25
  1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48,  1e-49,
 
26
  1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58,  1e-59,
 
27
};
 
28
 
 
29
#ifndef DBL_MAX
 
30
#define DBL_MAX 1.7976931348623157e+308
 
31
#endif
 
32
 
 
33
double strtod(const char *zNum, char **pzEnd){
 
34
  double rResult = 0.0;
 
35
  int isNegative = 0;
 
36
 
 
37
  while( isspace(*zNum) ){
 
38
    zNum++;
 
39
                        }
 
40
  if( *zNum=='-' ){
 
41
    zNum++;
 
42
    isNegative = 1;
 
43
  }else if( *zNum=='+' ){
 
44
    zNum++;
 
45
                        }
 
46
  while( isdigit(*zNum) ){
 
47
    rResult = rResult*10.0 + (*zNum - '0');
 
48
    zNum++;
 
49
                        }
 
50
  if( *zNum=='.' ){
 
51
    int n = 0;
 
52
    zNum++;
 
53
    while( isdigit(*zNum) ){
 
54
      if( n<sizeof(pastpoint)/sizeof(pastpoint[0]) ){
 
55
        rResult += pastpoint[n] * (*zNum - '0');
 
56
        n++;
 
57
                                        }
 
58
      zNum++;
 
59
                                }
 
60
                                }
 
61
  if( *zNum=='e' || *zNum=='E' ){
 
62
    int expVal = 0;
 
63
    int isNegExp = 0;
 
64
    const char *zExpStart = zNum;
 
65
    zNum++;
 
66
    if( *zNum=='-' ){
 
67
      isNegExp = 1;
 
68
      zNum++;
 
69
    }else if( *zNum=='+' ){
 
70
      zNum++;
 
71
                                }
 
72
    if( !isdigit(*zNum) ){
 
73
      zNum = zExpStart;
 
74
    }else{
 
75
      double scaler = 1.0;
 
76
      while( isdigit(*zNum) ){
 
77
        expVal = expVal*10 + *zNum - '0';
 
78
        zNum++;
 
79
                        }
 
80
      if( expVal >= 1000 ){
 
81
        if( isNegExp ){
 
82
          rResult = 0.0;
 
83
        }else{
 
84
          rResult = DBL_MAX;
 
85
                                }
 
86
        goto done;
 
87
                                }
 
88
      while( expVal >= 100 ){
 
89
        scaler *= 1.0e100;
 
90
        expVal -= 100;
 
91
                        }
 
92
      scaler *= scaler10[expVal/10]*scaler1[expVal%10];
 
93
      if( isNegExp ){
 
94
        scaler = 1.0/scaler;
 
95
                                }
 
96
      rResult *= scaler;
 
97
                        }
 
98
 
 
99
        }
 
100
 
 
101
done:
 
102
  if( pzEnd ){
 
103
    *pzEnd = (char *)zNum;
 
104
                }
 
105
  if( isNegative && rResult!=0.0 ){
 
106
    rResult = -rResult;
 
107
        }
 
108
  return rResult;
 
109
}
 
110
 
 
111
double atof(const char *nptr)
 
112
{
 
113
  return (strtod(nptr, 0));
 
114
}
 
115
 
 
116
#ifdef TEST
 
117
#undef strtod
 
118
 
 
119
double strtod(const char*,char**);
 
120
double NewStrtod(const char*,char**);
 
121
 
 
122
int main(int argc, char **argv){
 
123
  int nTest = 0;
 
124
  int nFail = 0;
 
125
  int nBigFail = 0;
 
126
  char zBuf[1000];
 
127
 
 
128
  while( fgets(zBuf,sizeof(zBuf),stdin) ){
 
129
    double old, new;
 
130
    char *zTailOld, *zTailNew;
 
131
    int i;
 
132
 
 
133
    for(i=0; zBuf[i] && zBuf[i]!='\n'; i++){}
 
134
    zBuf[i] = 0;
 
135
 
 
136
#if TEST==1
 
137
    printf("Input line: [%s]\n",zBuf);
 
138
    old = strtod(zBuf,&zTailOld);
 
139
    printf("value=%g\n",old);
 
140
    printf("Old:        0x%08x%08x  tail=[%s]\n",
 
141
           ((int*)&old)[1], ((int*)&old)[0], zTailOld);
 
142
    new = NewStrtod(zBuf,&zTailNew);
 
143
    printf("value=%g\n",new);
 
144
    printf("New:        0x%08x%08x  tail=[%s]\n\n",
 
145
           ((int*)&new)[1], ((int*)&new)[0], zTailNew);
 
146
#else
 
147
    old = strtod(zBuf,&zTailOld);
 
148
    new = NewStrtod(zBuf,&zTailNew);
 
149
    nTest++;
 
150
    if( strcmp(zTailOld,zTailNew) 
 
151
        || ((int*)&old)[0]!=((int*)&new)[0]
 
152
        || ((int*)&old)[1]!=((int*)&new)[1]
 
153
        ){
 
154
      int olda, oldb, newa, newb;
 
155
 
 
156
      nFail++;
 
157
      olda = ((int*)&old)[1];
 
158
      oldb = ((int*)&old)[0];
 
159
      newa = ((int*)&new)[1];
 
160
      newb = ((int*)&new)[0];
 
161
 
 
162
      if( olda!=newa || abs(oldb-newb)>2 ){
 
163
        nBigFail++;
 
164
        printf("******* Big failure \n");
 
165
                        }
 
166
      printf("Input = [%s]\n",zBuf);
 
167
      printf("old:   val=%g   0x%08x%08x  tail=[%s]\n",
 
168
             old, olda, oldb, zTailOld);
 
169
      printf("new:   val=%g   0x%08x%08x  tail=[%s]\n\n",
 
170
             new, newa, newb, zTailNew);
 
171
                                }
 
172
#endif
 
173
                        }
 
174
 
 
175
  printf("Out of %d tests, %d failures and %d big failurs\n",
 
176
         nTest,nFail, nBigFail);
 
177
}
 
178
#endif