getval.c File Reference

#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 Documentation

#define D   13

Definition at line 145 of file getval.c.

#define DGLIM   15

Definition at line 138 of file getval.c.

Referenced by getval().

#define dot   51

Definition at line 142 of file getval.c.

Referenced by ChooseOtherOperation(), getval(), parse(), and rd_L().

#define E   14

Definition at line 146 of file getval.c.

#define EXPLIM   22

Definition at line 139 of file getval.c.

Referenced by getval().

#define EXPMAX   309

Definition at line 135 of file getval.c.

#define EXPMIN   -324

Definition at line 136 of file getval.c.

Referenced by getval().

#define minus   46

Definition at line 144 of file getval.c.

Referenced by getval().

#define NDEMAX   7

Definition at line 137 of file getval.c.

Referenced by getval().

#define plus   45

Definition at line 143 of file getval.c.

Referenced by getval(), and Status2Mode().


Function Documentation

int C2F() fortrangetch (  ) 

Referenced by getval().

Here is the caller graph for this function:

int C2F() getval ( double *  s,
int dotdet 
)

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:


Generated on Sun Mar 4 15:14:58 2007 for Scilab [trunk] by  doxygen 1.5.1