home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 9.ddi / IOSTRSR1.ZIP / ISTELDBL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  7.3 KB  |  238 lines

  1. /*[]------------------------------------------------------------[]*/
  2. /*|                                                              |*/
  3. /*|     isteldbl.cpp                                             |*/
  4. /*|                                                              |*/
  5. /*|     Class istream                                            |*/
  6. /*|          istream& istream::operator>> ( long double& )       |*/
  7. /*|                                                              |*/
  8. /*[]------------------------------------------------------------[]*/
  9.  
  10. /*
  11.  *      C/C++ Run Time Library - Version 5.0
  12.  *
  13.  *      Copyright (c) 1990, 1992 by Borland International
  14.  *      All Rights Reserved.
  15.  *
  16.  */
  17.  
  18. /*
  19.  * If you have an optimized strtod() routine (or atof() or equivalent),
  20.  * you may wish to extract characters into a local string and call
  21.  * strtod() with that string instead of using the code given here.
  22.  *
  23.  * We take care to avoid floating-point overflow and underflow during all
  24.  * calculations and set errno to ERANGE on overflow and underflow, but
  25.  * we do not raise any error signals.
  26.  * You can speed up the code by removing the checks if they don't matter
  27.  * in your system.
  28.  *
  29.  * This code uses type long double exclusively, under the assumption
  30.  * that the math chips and the software floating-point library all
  31.  * convert all floats and doubles to long double internally.  It makes
  32.  * more sense to do this conversion once on input and once on output
  33.  * rather than multiple times.
  34.  */
  35.  
  36. #include <ioconfig.h>
  37. #include <iostream.h>
  38. #include <ctype.h>
  39. #include <float.h>  // for characteristics of floating types
  40. #include <math.h>      // for HUGE_VAL
  41. #include <errno.h>  // for reporting range errors
  42.  
  43.  
  44.  
  45. /*
  46.  * The following defines are for type long double.
  47.  * If you want to do float or long separately,
  48.  * you will need to supply the appropriate values
  49.  */
  50. #define Dbigexp 49320L      // much bigger than any power 10 exponent
  51. #define Dmaxint 493200L     // (10*Dbigexp)
  52. #define Dfixexp 2466L       // about max_10_exp / 2
  53. #define Dfixval 1.0e2466    // 10 ** Dfixexp
  54.  
  55.  
  56. istream _FAR & istream::operator>> (long double _FAR & val)
  57. {
  58.     if( ipfx0() )
  59.         {     // verify file state and possibly skip white
  60.  
  61.         int c;          // current input character
  62.         int negval;     // entire value is negative
  63.         int negexp;     // exponent is negative
  64.         long exp;       // accumulated exponent
  65.         int formok;     // floating-point number format is valid
  66.  
  67.         formok = 0;     // until proven otherwise
  68.         c = bp->sgetc();    // look at first character
  69.  
  70.         // get leading sign
  71.         negval = c == '-';
  72.         if( c == '+'  ||  negval )
  73.             c = bp->snextc();
  74.         else if( c == EOF )
  75.             setstate(ios::badbit);  // no characters extracted
  76.  
  77.         // scan off digits up to decimal point
  78.         val = 0.0;
  79.         if( isdigit(c) )
  80.             {
  81.             formok = 1;
  82.             do  {
  83.                 c -= '0';
  84.                 val = 10.0 * val + c;
  85.                 c = bp->snextc();
  86.                 } while( isdigit(c) );
  87.             }
  88.  
  89.         // scan off fractional digits, keeping count
  90.         exp = 0;
  91.         if( c == '.' )
  92.             {
  93.             c = bp->snextc();
  94.             if( isdigit(c) )
  95.                 {
  96.                 formok = 1;
  97.                 do  {
  98.                     c -= '0';
  99.                     val = 10.0 * val + c;
  100.                     --exp;
  101.                     c = bp->snextc();
  102.                     } while( isdigit(c) );
  103.                 }
  104.             }
  105.  
  106.         // look for possibly-signed exponent
  107.         if( formok  &&  (c == 'e'  ||  c == 'E') )
  108.             {
  109.             c = bp->snextc();
  110.             formok = isdigit(c)  ||  c == '+'  ||  c == '-';
  111.  
  112.             long givenexp = 0;  // exponent given in E... part of number
  113.             if( ! formok )
  114.                 val = 0.0;
  115.             else
  116.                 {
  117.                 // convert possibly-signed exponent
  118.                 negexp = c == '-';  // here we mean the given exponent
  119.                 if( c == '+'  ||  negexp )
  120.                     c = bp->snextc();
  121.                 formok = isdigit(c);
  122.                 if( ! formok )
  123.                     val = 0.0;
  124.                 else
  125.                     {
  126.                     do  {
  127.                         if( givenexp < Dbigexp )
  128.                             {
  129.                             c -= '0';
  130.                             givenexp = 10 * givenexp + c;
  131.                             }
  132.                         c = bp->snextc();
  133.                         } while( isdigit(c) );
  134.                     }
  135.                 }
  136.  
  137.             // adjust exponent by given exponent, watching for overflow
  138.             if( negexp )
  139.                 {
  140.                 if( givenexp - Dmaxint < exp )
  141.                     exp -= givenexp;
  142.                 else
  143.                     exp = - Dmaxint;
  144.                 }
  145.             else
  146.                 {
  147.                 if( Dmaxint - givenexp > exp )
  148.                     exp += givenexp;
  149.                 else
  150.                     exp = Dmaxint;
  151.                 }
  152.         }
  153.  
  154.     // try to salvage some underflow
  155.     if( exp <= LDBL_MIN_10_EXP )
  156.         {
  157.         val /= Dfixval;
  158.         exp += Dfixexp;;
  159.         }
  160.  
  161.     // final calculation
  162.     if( exp < LDBL_MIN_10_EXP )
  163.         {
  164.         val = 0.0;
  165.         errno = ERANGE;
  166.         }
  167.     else if( exp > LDBL_MAX_10_EXP )
  168.         {
  169.         val = HUGE_VAL;
  170.         errno = ERANGE;
  171.         }
  172.     else if( formok )
  173.         {
  174.         int overflow = 0;           // did overflow occur
  175.         long double adjust = 1.0;   // amount to adjust because of exponent
  176.         long double power = 10.0;   // used in building adjust
  177.         negexp = exp < 0;           // negexp now refers to net exponent
  178.         if( negexp )
  179.             exp = -exp;     // exp is now absolute value
  180.  
  181.         // compute val * (10 ** exp)
  182.         while( exp > 0 )
  183.             {
  184.             if( exp & 1 )
  185.                 {
  186.                 if( LDBL_MAX / adjust >= power )
  187.                     adjust *= power;
  188.                 else
  189.                     overflow = 1;
  190.                 }
  191.             exp >>= 1;
  192.             if( exp > 0 )
  193.                 {
  194.                 if( LDBL_MAX / power >= power )
  195.                     power *= power;
  196.                 else
  197.                     overflow = 1;
  198.                 }
  199.             }
  200.  
  201.         if( ! overflow )
  202.             {
  203.             if( adjust != 1.0 )
  204.                 {
  205.                 if( negexp )
  206.                     val /= adjust;
  207.                 else if( val <= 1.0 )
  208.                     val *= adjust;
  209.                 else if( LDBL_MAX / val >= adjust )
  210.                     val *= adjust;
  211.                 else
  212.                     overflow = 1;
  213.                 }
  214.             }
  215.         if( overflow )
  216.             {
  217.             if( negexp )
  218.                 val = 0.0;
  219.             else
  220.                 val = HUGE_VAL;
  221.             errno = ERANGE;
  222.             }
  223.         }
  224.  
  225.     if( formok )
  226.         {
  227.         if( negval )
  228.             val = -val; // adjust the sign
  229.         }
  230.     else if( c == EOF)
  231.         setstate(ios::eofbit | ios::failbit);
  232.     else
  233.         setstate(ios::failbit);
  234.     }
  235.  
  236.     return *this;
  237. }
  238.