home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / Numbers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  7.8 KB  |  310 lines  |  [TEXT/KAHL]

  1. /* Numbers.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "Numbers.h"
  25. #include "Memory.h"
  26. #include "FloatingPoint.h"
  27.  
  28.  
  29. #define FLOATTOSTRINGBUFSIZE (128)
  30.  
  31.  
  32. long                        StringToInteger(char* String, long Length)
  33.     {
  34.         return (long)StringToLongDouble(String,Length);
  35.     }
  36.  
  37.  
  38. char*                        IntegerToString(long Integer)
  39.     {
  40.         char*                    Temp;
  41.  
  42.         Temp = LongDoubleToString(Integer,37,1e-37,1e37); /* these bounds should be enough */
  43.         if (Temp != NIL)
  44.             {
  45.                 SetTag(Temp,"IntegerToString");
  46.             }
  47.         return Temp;
  48.     }
  49.  
  50.  
  51. long double            StringToLongDouble(char* String, long Length)
  52.     {
  53.         long double        Accumulator;
  54.         MyBoolean            Negative;
  55.         MyBoolean            Decimal;
  56.         long double        DecimalScan;
  57.         long                    Exponent;
  58.         long                    Scan;
  59.  
  60.         Negative = False;
  61.         Decimal = False;
  62.         Scan = 0;
  63.         while (Scan < Length)
  64.             {
  65.                 switch (String[Scan])
  66.                     {
  67.                         case '+':
  68.                         case ' ':
  69.                             break;
  70.                         case '-':
  71.                             /* this might not be a good idea... what does the */
  72.                             /* average user think? */
  73.                             Negative = !Negative;
  74.                             break;
  75.                         default:
  76.                             goto ContinuePoint;
  77.                     }
  78.                 Scan += 1;
  79.             }
  80.      ContinuePoint:
  81.         Accumulator = 0;
  82.         while (Scan != Length)
  83.             {
  84.                 switch (String[Scan])
  85.                     {
  86.                         default:
  87.                             goto ExitPoint;
  88.                         case '.':
  89.                             DecimalScan = 0.1;
  90.                             Decimal = True;
  91.                             break;
  92.                         case '0': case '1': case '2': case '3': case '4':
  93.                         case '5': case '6': case '7': case '8': case '9':
  94.                             if (!Decimal)
  95.                                 {
  96.                                     Accumulator = (10 * Accumulator) + (String[Scan] - '0');
  97.                                 }
  98.                              else
  99.                                 {
  100.                                     Accumulator = Accumulator + (DecimalScan * (String[Scan] - '0'));
  101.                                     DecimalScan = DecimalScan / 10;
  102.                                 }
  103.                             break;
  104.                         case 'e': case 'E':
  105.                             Exponent = StringToInteger(&(String[Scan + 1]),Length - Scan - 1);
  106.                             while (Exponent < 0)
  107.                                 {
  108.                                     Exponent += 1;
  109.                                     Accumulator /= 10;
  110.                                 }
  111.                             while (Exponent > 0)
  112.                                 {
  113.                                     Exponent -= 1;
  114.                                     Accumulator *= 10;
  115.                                 }
  116.                             goto ExitPoint;
  117.                     }
  118.                 Scan += 1;
  119.             }
  120.      ExitPoint:
  121.         if (Negative)
  122.             {
  123.                 Accumulator = - Accumulator;
  124.             }
  125.         return Accumulator;
  126.     }
  127.  
  128.  
  129. char*                        LongDoubleToString(long double Value, int NumDigits,
  130.                                     long double LowBound, long double HighBound)
  131.     {
  132.         char                    Buffer[FLOATTOSTRINGBUFSIZE];
  133.         int                        Index;
  134.         MyBoolean            ScientificNotation;
  135.         MyBoolean            Negative;
  136.         long                    Exponent;
  137.         long double        Checker;
  138.         MyBoolean            DecimalEmitted;
  139.         char*                    Thang;
  140.  
  141.         /* rounding */
  142.         Checker = Value;
  143.         for (Index = 0; Index < NumDigits; Index += 1)
  144.             {
  145.                 Checker = Checker / 10;
  146.             }
  147.         Value += Checker / 2;
  148.  
  149.         /* initialize buffer pointer */
  150.         Index = 0;
  151.         if (NumDigits > FLOATTOSTRINGBUFSIZE - 16)
  152.             {
  153.                 NumDigits = FLOATTOSTRINGBUFSIZE - 16;
  154.             }
  155.  
  156.         /* NaN check */
  157.         if (ISNAN(Value))
  158.             {
  159.                 Buffer[Index++] = 'N';
  160.                 Buffer[Index++] = 'a';
  161.                 Buffer[Index++] = 'N';
  162.                 goto AllDonePoint;
  163.             }
  164.  
  165.         /* handle negative values right now */
  166.         Negative = (Value < 0);
  167.         if (Negative)
  168.             {
  169.                 Value = - Value;
  170.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  171.                     "LongDoubleToString:  buffer overflow"));
  172.                 Buffer[Index++] = '-';
  173.             }
  174.  
  175.         /* if value is equal to zero, return zero right now */
  176.         if (Value == 0)
  177.             {
  178.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  179.                     "LongDoubleToString:  buffer overflow"));
  180.                 Buffer[Index++] = '0';
  181.                 goto AllDonePoint;
  182.             }
  183.  
  184.         /* determine if we need to use scientific notation by */
  185.         /* comparing against the bounds passed in */
  186.         ScientificNotation = ((Value < LowBound) || (Value >= HighBound));
  187.         if (ScientificNotation)
  188.             {
  189.                 /* if it is scientific notation, we want to normalize the number */
  190.                 /* and remember what exponent we should output */
  191.                 Exponent = 0;
  192.                 while (Value < 1)
  193.                     {
  194.                         Value = Value * 10;
  195.                         Exponent -= 1;
  196.                     }
  197.                 while (Value >= 10)
  198.                     {
  199.                         Value = Value / 10;
  200.                         Exponent += 1;
  201.                     }
  202.             }
  203.  
  204.         /* increment the checker thing until it is high enough */
  205.         Checker = 1;
  206.         while (Checker * 10 <= Value)
  207.             {
  208.                 Checker = Checker * 10;
  209.             }
  210.  
  211.         /* perform the actual scan */
  212.         DecimalEmitted = False;
  213.         while ((Checker >= 1) || ((NumDigits > 0) && (Value != 0)))
  214.             {
  215.                 int                    Count;
  216.  
  217.                 /* find out what digit to put */
  218.                 Count = 0;
  219.                 while (Value >= ((Count + 1) * Checker))
  220.                     {
  221.                         Count += 1;
  222.                     }
  223.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  224.                     "LongDoubleToString:  buffer overflow"));
  225.                 Buffer[Index++] = '0' + Count;
  226.                 Value -= Count * Checker;
  227.                 /* decrement digit count */
  228.                 NumDigits -= 1;
  229.                 /* put a decimal if appropriate */
  230.                 if (!DecimalEmitted && (Checker == 1) && (NumDigits > 0) && (Value != 0))
  231.                     {
  232.                         DecimalEmitted = True;
  233.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  234.                             "LongDoubleToString:  buffer overflow"));
  235.                         Buffer[Index++] = '.';
  236.                     }
  237.                 /* decrement digit position */
  238.                 Checker /= 10;
  239.             }
  240.  
  241.         /* drop trailing zeros */
  242.         if (DecimalEmitted)
  243.             {
  244.                 while (Buffer[Index - 1] == '0')
  245.                     {
  246.                         Index -= 1;
  247.                     }
  248.                 if (Buffer[Index - 1] == '.')
  249.                     {
  250.                         Index -= 1;
  251.                         DecimalEmitted = False;
  252.                     }
  253.             }
  254.  
  255.         /* if it was scientific notation, then put the exponent on */
  256.         if (ScientificNotation)
  257.             {
  258.                 long                    IntChecker;
  259.  
  260.                 /* put the 'e' */
  261.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  262.                     "LongDoubleToString:  buffer overflow"));
  263.                 Buffer[Index++] = 'e';
  264.                 /* check for negative exponent */
  265.                 if (Exponent < 0)
  266.                     {
  267.                         Exponent = - Exponent;
  268.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  269.                             "LongDoubleToString:  buffer overflow"));
  270.                         Buffer[Index++] = '-';
  271.                     }
  272.                 /* initialize the integer thing */
  273.                 IntChecker = 1;
  274.                 while ((IntChecker * 10) <= Exponent)
  275.                     {
  276.                         /* we don't have to worry about integer overflow because even */
  277.                         /* a long double's exponent doesn't approach the integer's limit */
  278.                         IntChecker *= 10;
  279.                     }
  280.                 /* perform the integer conversion scan */
  281.                 while (IntChecker > 0)
  282.                     {
  283.                         int                    Count;
  284.  
  285.                         /* figure out the digit's value */
  286.                         Count = 0;
  287.                         while (Exponent >= ((Count + 1) * IntChecker))
  288.                             {
  289.                                 Count += 1;
  290.                             }
  291.                         /* emit the digit */
  292.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  293.                             "LongDoubleToString:  buffer overflow"));
  294.                         Buffer[Index++] = '0' + Count;
  295.                         /* update the values */
  296.                         Exponent -= Count * IntChecker;
  297.                         IntChecker /= 10;
  298.                     }
  299.             }
  300.  
  301.         /* finally, create the thang so we can output it */
  302.      AllDonePoint:
  303.         Thang = AllocPtrCanFail(Index,"LongDoubleToString");
  304.         if (Thang != NIL)
  305.             {
  306.                 CopyData(&(Buffer[0]),&(Thang[0]),Index);
  307.             }
  308.         return Thang;
  309.     }
  310.