summaryrefslogtreecommitdiff
path: root/lib/libpthread/stdlib/strtod.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/stdlib/strtod.c')
-rw-r--r--lib/libpthread/stdlib/strtod.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/lib/libpthread/stdlib/strtod.c b/lib/libpthread/stdlib/strtod.c
new file mode 100644
index 00000000000..173ca1e4bdf
--- /dev/null
+++ b/lib/libpthread/stdlib/strtod.c
@@ -0,0 +1,178 @@
+/*
+** An alternative implemtation of "strtod()" that is both
+** simplier, and thread-safe.
+*/
+#include <pthread.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifdef TEST
+# define strtod NewStrtod
+#include <stdio.h>
+#endif
+
+static double scaler10[] = {
+ 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
+};
+static double scaler1[] = {
+ 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
+};
+static double pastpoint[] = {
+ 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9,
+ 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19,
+ 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29,
+ 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 1e-39,
+ 1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48, 1e-49,
+ 1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58, 1e-59,
+};
+
+#ifndef DBL_MAX
+#define DBL_MAX 1.7976931348623157e+308
+#endif
+
+double strtod(const char *zNum, char **pzEnd){
+ double rResult = 0.0;
+ int isNegative = 0;
+
+ while( isspace(*zNum) ){
+ zNum++;
+ }
+ if( *zNum=='-' ){
+ zNum++;
+ isNegative = 1;
+ }else if( *zNum=='+' ){
+ zNum++;
+ }
+ while( isdigit(*zNum) ){
+ rResult = rResult*10.0 + (*zNum - '0');
+ zNum++;
+ }
+ if( *zNum=='.' ){
+ int n = 0;
+ zNum++;
+ while( isdigit(*zNum) ){
+ if( n<sizeof(pastpoint)/sizeof(pastpoint[0]) ){
+ rResult += pastpoint[n] * (*zNum - '0');
+ n++;
+ }
+ zNum++;
+ }
+ }
+ if( *zNum=='e' || *zNum=='E' ){
+ int expVal = 0;
+ int isNegExp = 0;
+ const char *zExpStart = zNum;
+ zNum++;
+ if( *zNum=='-' ){
+ isNegExp = 1;
+ zNum++;
+ }else if( *zNum=='+' ){
+ zNum++;
+ }
+ if( !isdigit(*zNum) ){
+ zNum = zExpStart;
+ }else{
+ double scaler = 1.0;
+ while( isdigit(*zNum) ){
+ expVal = expVal*10 + *zNum - '0';
+ zNum++;
+ }
+ if( expVal >= 1000 ){
+ if( isNegExp ){
+ rResult = 0.0;
+ }else{
+ rResult = DBL_MAX;
+ }
+ goto done;
+ }
+ while( expVal >= 100 ){
+ scaler *= 1.0e100;
+ expVal -= 100;
+ }
+ scaler *= scaler10[expVal/10]*scaler1[expVal%10];
+ if( isNegExp ){
+ scaler = 1.0/scaler;
+ }
+ rResult *= scaler;
+ }
+
+ }
+
+done:
+ if( pzEnd ){
+ *pzEnd = (char *)zNum;
+ }
+ if( isNegative && rResult!=0.0 ){
+ rResult = -rResult;
+ }
+ return rResult;
+}
+
+double atof(const char *nptr)
+{
+ return (strtod(nptr, 0));
+}
+
+#ifdef TEST
+#undef strtod
+
+double strtod(const char*,char**);
+double NewStrtod(const char*,char**);
+
+int main(int argc, char **argv){
+ int nTest = 0;
+ int nFail = 0;
+ int nBigFail = 0;
+ char zBuf[1000];
+
+ while( fgets(zBuf,sizeof(zBuf),stdin) ){
+ double old, new;
+ char *zTailOld, *zTailNew;
+ int i;
+
+ for(i=0; zBuf[i] && zBuf[i]!='\n'; i++){}
+ zBuf[i] = 0;
+
+#if TEST==1
+ printf("Input line: [%s]\n",zBuf);
+ old = strtod(zBuf,&zTailOld);
+ printf("value=%g\n",old);
+ printf("Old: 0x%08x%08x tail=[%s]\n",
+ ((int*)&old)[1], ((int*)&old)[0], zTailOld);
+ new = NewStrtod(zBuf,&zTailNew);
+ printf("value=%g\n",new);
+ printf("New: 0x%08x%08x tail=[%s]\n\n",
+ ((int*)&new)[1], ((int*)&new)[0], zTailNew);
+#else
+ old = strtod(zBuf,&zTailOld);
+ new = NewStrtod(zBuf,&zTailNew);
+ nTest++;
+ if( strcmp(zTailOld,zTailNew)
+ || ((int*)&old)[0]!=((int*)&new)[0]
+ || ((int*)&old)[1]!=((int*)&new)[1]
+ ){
+ int olda, oldb, newa, newb;
+
+ nFail++;
+ olda = ((int*)&old)[1];
+ oldb = ((int*)&old)[0];
+ newa = ((int*)&new)[1];
+ newb = ((int*)&new)[0];
+
+ if( olda!=newa || abs(oldb-newb)>2 ){
+ nBigFail++;
+ printf("******* Big failure \n");
+ }
+ printf("Input = [%s]\n",zBuf);
+ printf("old: val=%g 0x%08x%08x tail=[%s]\n",
+ old, olda, oldb, zTailOld);
+ printf("new: val=%g 0x%08x%08x tail=[%s]\n\n",
+ new, newa, newb, zTailNew);
+ }
+#endif
+ }
+
+ printf("Out of %d tests, %d failures and %d big failurs\n",
+ nTest,nFail, nBigFail);
+}
+#endif