#include <string.h>#include <stdio.h>#include <math.h>#include <stdlib.h>#include "stack-c.h"#include "getval.h"Include dependency graph for getval.c:

Go to the source code of this file.
Defines | |
| #define | EXPMAX 309 |
| #define | EXPMIN -324 |
| #define | NDEMAX 7 |
| #define | DGLIM 15 |
| #define | EXPLIM 22 |
| #define | dot 51 |
| #define | plus 45 |
| #define | minus 46 |
| #define | D 13 |
| #define | E 14 |
Functions | |
| int C2F() | fortrangetch () |
| int C2F() | getval (double *s, int *dotdet) |
| #define dot 51 |
| #define plus 45 |
Definition at line 151 of file getval.c.
References abs, C2F, char1, D, DGLIM, dot, E, EXPLIM, EXPMAX, EXPMIN, fortrangetch(), i, i1, minus, NDEMAX, NULL, plus, s, string, and TRUE_.
00152 { 00153 /* Initialized constants */ 00154 static double toto = 0.; 00155 static double c10 = 10.; 00156 00157 /* Local variables */ 00158 static int expo; 00159 static int code0; 00160 static int i, k; 00161 static int digit[25], ndgrec; 00162 static int detdot; 00163 static int ndgexp, expcor, sgnexp; 00164 static char string[31]; 00165 static int ndg; 00166 00167 /* System generated locals */ 00168 static double d1; 00169 int i1; 00170 00171 C2F(com).fin = 0; 00172 /* beginning of the code */ 00173 detdot = *dotdet; 00174 ndg = 0; 00175 ndgrec = 0; 00176 if (! detdot) { 00177 /* 1) got the integer part of the mantissa of the pattern 00178 1-a) may be there is some 0 at the beginning */ 00179 while(C2F(com).char1 == 0) { 00180 C2F(fortrangetch)(); 00181 } 00182 /* 1-b) now record the digits (inside the digit array) 00183 (but we record a maximum of ndgmax digits)*/ 00184 while(abs(C2F(com).char1) <= 9) { 00185 ++ndg; 00186 if (ndgrec < 25) { 00187 ++ndgrec; 00188 digit[ndgrec - 1] = C2F(com).char1; 00189 } 00190 C2F(fortrangetch)(); 00191 } 00192 /*1-c) at this point we have detected something which is not a digit 00193 may be a point, may be a d,D,e,E, or something else 00194 here we only test for the dot and let the others cases 00195 to be treated after ... */ 00196 if (abs(C2F(com).char1) == dot) { 00197 detdot = TRUE_; 00198 C2F(fortrangetch)(); 00199 } 00200 } 00201 /*first correction for the (future) exponent : if the first part 00202 of the string have more then ndgmax digits we have to add 00203 ndg - ndgrec (else we have expcor=0) */ 00204 expcor = ndg - ndgrec; 00205 if (detdot) { 00206 /*2) got the "fractionnal" part of the "mantissa" */ 00207 if (ndgrec == 0) { 00208 /*we have not passed throw the part 1) or only zeros have been met 00209 and may be the number start with .000xxx : so clean up those 0 */ 00210 while(C2F(com).char1 == 0) { 00211 --expcor; 00212 C2F(fortrangetch)(); 00213 } 00214 } 00215 /*now we begin to record the digits */ 00216 while(abs(C2F(com).char1) <= 9) { 00217 if (ndgrec < 25) { 00218 ++ndgrec; 00219 --expcor; 00220 digit[ndgrec - 1] = C2F(com).char1; 00221 } 00222 C2F(fortrangetch)(); 00223 } 00224 } 00225 /*3) at this point the "mantissa" of the string decimal number 00226 must be recorded, now detect the exponent */ 00227 expo = 0; 00228 ndgexp = 0; 00229 sgnexp = plus; 00230 if (abs(C2F(com).char1) == D || abs(C2F(com).char1) == E) { 00231 /*the string have an exponent part (which, in Scilab, may be empty or 00232 may had only a sign ! => expo = 0) */ 00233 C2F(fortrangetch)(); 00234 if (C2F(com).char1 == minus || C2F(com).char1 == plus) { 00235 sgnexp = C2F(com).char1; 00236 C2F(fortrangetch)(); 00237 } else { 00238 sgnexp = plus; 00239 } 00240 /*may be the exponent start by some 0 */ 00241 while(C2F(com).char1 == 0) { 00242 C2F(fortrangetch)(); 00243 } 00244 /*now form the exponent : the var ndgexp is here 00245 to treat spurious integer overflow ... */ 00246 while(abs(C2F(com).char1) <= 9) { 00247 expo = expo * 10 + C2F(com).char1; 00248 ++ndgexp; 00249 C2F(fortrangetch)(); 00250 } 00251 } 00252 /*4) Now we can form the double float number s 00253 4-1/ only zeros in the mantissa */ 00254 if (ndgrec == 0) { 00255 /*no digits have been recorded : this is the case 00256 when the mantissa part is of the form [000][.][000] 00257 the number is 0 */ 00258 *s = 0.; 00259 return 0; 00260 } 00261 /*4-2/ ndgexp is to large => the exponent expo is perhaps badly 00262 computed (integer "overflow") or in all cases the 00263 exponent is too large (positive or negative) such that it result 00264 (for s) in a overflow or underflow depending the exponent sign */ 00265 if (ndgexp >= NDEMAX) { 00266 if (sgnexp == minus) {/*underflow */ 00267 *s = 0.; 00268 } else {/*overflow : got an inf ... */ 00269 *s = 1. / (toto - toto); 00270 } 00271 return 0; 00272 } 00273 /*4-3/ now build the final exponent */ 00274 if (sgnexp == plus) { 00275 expo += expcor; 00276 } else { 00277 expo = -expo + expcor; 00278 } 00279 /*4-4/ here some tests to avoid unnecessary call to "strtod" 00280 Now we have a number s of the form d_1 d_2 ... d_ndgrec 10^expo 00281 which is equal to d_1 . d_2 ... d_ndgrec 10^(expo + ndgrec - 1) 00282 with d_1 .ne. 0 00283 so it comes : s >= 10^(expo + ndgrec - 1) 00284 s <= 10^(expo + ndgrec) 00285 00286 Suppose given EXPMAX such that 10^EXPMAX > max positive float number 00287 and EXPMIN such that 10^EXPMIN < min positive float number 00288 00289 then if expo + ndgrec - 1 >= EXPMAX then overflow occurs necessarily 00290 and if expo + ndgrec <= EXPMIN then underflow occurs 00291 00292 On IEEE 754 we have : max positive float num = (approx) 1.8E+308 00293 min positive float num = (approx) 4.9EEXPMIN 00294 (if denormalised number are used) 00295 00296 So that EXPMAX = 309 00297 and EXPMIN = -324 are OK (but larger limits are possible to take 00298 into account others f.p. arithmetics) 00299 Note that after the test (with these values) the exponent have a 00300 maximum of 3 (decimals) digits */ 00301 if (expo + ndgrec - 1 >= EXPMAX) {/*overflow : got an inf ... */ 00302 *s = 1. / (toto - toto); 00303 return 0; 00304 } 00305 if (expo + ndgrec <= EXPMIN) { /*underflow : got an 0 */ 00306 *s = 0.; 00307 return 0; 00308 } 00309 /*4-5/ Now the usual case where we can get the near floating point 00310 without any problem */ 00311 if (ndgrec <= DGLIM && abs(expo) <= EXPLIM) { 00312 *s = 0.; 00313 i1 = ndgrec; 00314 for (i = 1; i <= i1; ++i) { 00315 *s = *s * 10. + digit[i - 1]; 00316 } 00317 if (expo < 0) { 00318 d1 = -expo; 00319 *s /= pow(c10, d1); 00320 } else { 00321 d1 = expo; 00322 *s *= pow(c10, d1); 00323 } 00324 return 0; 00325 } 00326 /*4-6/ The other easy case where we can compute s : 00327 if expo = EXPLIM + k but [integer part]*10^k < max_int_coded_in_double 00328 then it is OK (retrieve k in the exponent and multiply the integer 00329 part by 10^k and do the same job as previus) */ 00330 if (expo > EXPLIM && expo - EXPLIM + ndgrec <= DGLIM) { 00331 *s = 0.; 00332 i1 = ndgrec; 00333 for (i = 1; i <= i1; ++i) { 00334 *s = *s * 10. + digit[i - 1]; 00335 } 00336 /*peut etre dangereux avec des options d'optimisation ? 00337 (le compilo peut etre tente d'ecrire directement s = s*10**expo 00338 ce qui detruit le truc ...) */ 00339 /* s = s*10.d0**(expo-EXPLIM) 00340 s = s*10.d0**EXPLIM*/ 00341 00342 d1 = (double)(expo - EXPLIM); 00343 *s *= pow(c10,d1); 00344 d1 = (double) EXPLIM; 00345 *s *= pow(c10, d1); 00346 00347 return 0; 00348 } 00349 /*4-7/ else use langage routines to do the job 00350 the overhead is a retranslation into a string... */ 00351 code0 = '0'; 00352 i1 = ndgrec; 00353 for (i = 1; i <= i1; ++i) { 00354 *(unsigned char *)&string[i - 1] = (char) (digit[i - 1] + code0); 00355 } 00356 i1 = ndgrec; 00357 if (expo < 0) { 00358 sprintf(string+i1,".e-%d",abs(expo)); 00359 } else { 00360 sprintf(string+i1,".e+%d",abs(expo)); 00361 } 00362 k = ndgrec + 4; 00363 *s=strtod(string,NULL); 00364 return 0; 00365 }
Here is the call graph for this function:

1.5.1