home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / double.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-24  |  15.6 KB  |  422 lines

  1. // $Id: double.h,v 1.15 2001/02/17 06:26:55 mdejong Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. //
  11. // NOTE: The IEEE 754 emulation code in double.h and double.cpp within
  12. // Jikes are adapted from code written by Alan M. Webb of IBM's Hursley
  13. // lab in porting the Sun JDK to System/390.
  14. //
  15. // In addition, the code for emulating the remainder operator, %, is
  16. // adapted from e_fmod.c, part of fdlibm, the Freely Distributable Math
  17. // Library mentioned in the documentation of java.lang.StrictMath.  The
  18. // original library is available at http://netlib2.cs.utk.edu/fdlibm.
  19. //
  20. // The code from fdlibm is copyrighted, as follows:
  21. // ====================================================
  22. // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  23. //
  24. // Developed at SunSoft, a Sun Microsystems, Inc. business.
  25. // Permission to use, copy, modify, and distribute this
  26. // software is freely granted, provided that this notice 
  27. // is preserved.
  28. // ====================================================
  29. //
  30. //
  31.  
  32. #ifndef Double_INCLUDED
  33. #define Double_INCLUDED
  34.  
  35. #include "platform.h"
  36. #include "long.h"
  37.  
  38. #ifdef    HAVE_JIKES_NAMESPACE
  39. namespace Jikes {    // Open namespace Jikes block
  40. #endif
  41.  
  42. class LongInt;
  43. class IEEEdouble;
  44.  
  45. class IEEEfloat
  46. {
  47.     //
  48.     // If HAVE_IEEE754 is defined, this class is simply a wrapper for
  49.     // compiler-supported IEEE operations.  If not, then this class
  50.     // emulates IEEE 754 behavior, in acccordance with the Java Language,
  51.     // using only integer arithmetic.
  52.     //
  53. private:
  54.     union
  55.     {
  56.         float float_value;
  57.         u4 word; // unsigned
  58.         i4 iword; // signed
  59.     } value;
  60.  
  61.     enum { FRACT_BITS = 23, BIAS = 127 };
  62.  
  63.     inline u4 SignBit(void)  { return value.word & 0x80000000; }
  64.     inline u4 ExpBits(void)  { return value.word & 0x7F800000; }
  65.  
  66.     // takes the (possibly) unnormalized fraction with its corresponding
  67.     // exponent and sign, and creates the normalized float
  68.     static IEEEfloat Normalize(int, int, u4);
  69.     // takes the float and splits it into a normalized fraction and exponent;
  70.     // the exponent is returned, the parameter fraction is modified
  71.     int SplitInto(u4 &fraction);
  72.  
  73. #ifndef HAVE_MEMBER_CONSTANTS
  74.     // VC++ can't cope with constant class members
  75.     static u4 MAX_FRACT;
  76.     static u4 MAX_FRACT2;
  77.     static u4 MIN_INT_F;
  78.     static i4 MIN_INT;
  79.     static i4 MAX_INT;
  80. #else
  81.     static const u4 MAX_FRACT   = 0x01000000;
  82.     static const u4 MAX_FRACT2  = 0x00800000;
  83.     static const u4 MIN_INT_F   = 0xCF000000;
  84.     static const i4 MIN_INT     = 0x80000000;
  85.     static const i4 MAX_INT     = 0x7FFFFFFF;
  86. #endif
  87.  
  88. public:
  89.     //
  90.     // Information methods, for evaluating components of the float
  91.     //
  92.     inline u4 Word(void) { return value.word; }
  93.  
  94.     inline int  Sign(void)       { return value.word >> 31; }
  95.     inline int  Exponent(void)   { return ((value.iword >> 23) & 0x000000FF) - BIAS; }
  96.     inline u4   Fraction(void)   { return (value.word & 0x007FFFFF)
  97.                                           | (ExpBits() ? 0x00800000 : 0); }
  98.  
  99.     inline bool IsNaN(void)      { return (value.word & 0x7FFFFFFF) > 0x7F800000; }
  100.  
  101.     inline bool IsNegative(void) { return (value.iword < 0) && !IsNaN(); }
  102.     inline bool IsPositive(void) { return (value.iword >= 0) && !IsNaN(); }
  103.  
  104.     inline bool IsNegativeZero(void)     { return value.word == 0x80000000; }
  105.     inline bool IsPositiveZero(void)     { return value.word == 0x00000000; }
  106.     inline bool IsZero(void)             { return (value.word & 0x7FFFFFFF) == 0x00000000; }
  107.  
  108.     inline bool IsNegativeInfinity(void) { return value.word == 0xFF800000; }
  109.     inline bool IsPositiveInfinity(void) { return value.word == 0x7F800000; }
  110.     inline bool IsInfinite(void)         { return (value.word & 0x7FFFFFFF) == 0x7F800000; }
  111.  
  112.  
  113.     //
  114.     // Generation methods, for creating common constants
  115.     //
  116.     static inline IEEEfloat NaN(void)               { return IEEEfloat(0x7FC00000U); }
  117.     static inline IEEEfloat POSITIVE_INFINITY(void) { return IEEEfloat(0x7F800000U); }
  118.     static inline IEEEfloat NEGATIVE_INFINITY(void) { return IEEEfloat(0xFF800000U); }
  119.     static inline IEEEfloat POSITIVE_ZERO(void)     { return IEEEfloat(0x00000000U); }
  120.     static inline IEEEfloat NEGATIVE_ZERO(void)     { return IEEEfloat(0x80000000U); }
  121.  
  122.  
  123.     //
  124.     // Constructors
  125.     //
  126.     // Create a float from the given value
  127.     inline   IEEEfloat(float f) { value.float_value = f; }
  128.  
  129.     // Convert string to float, the float is NaN if check_invalid is true and input is invalid by JLS
  130.              IEEEfloat(char *, bool check_invalid = false);
  131.     // Widening conversion of int to float, may lose precision
  132.              IEEEfloat(i4);
  133.     // Widening conversion of long to float, may lose precision
  134.              IEEEfloat(LongInt);
  135.     // Narrowing conversion of double to float, may lose precision
  136. #ifdef HAVE_EXPLICIT
  137.     explicit
  138. #endif
  139.              IEEEfloat(IEEEdouble);
  140.     // Create a float without initializing it
  141.     inline   IEEEfloat(void) {}
  142.  
  143.     // Load a specified bit pattern (contrast to IEEEfloat(i4))
  144.     inline   IEEEfloat(u4 bits) { value.word = bits; }
  145.  
  146.  
  147.     //
  148.     // Conversion routines
  149.     //
  150.            i4         IntValue(void);
  151.            LongInt    LongValue(void);
  152.     inline float      FloatView(void) { return value.float_value; }
  153.     inline IEEEdouble DoubleValue(void);
  154.  
  155.  
  156.     //
  157.     // Floating-point operations
  158.     // TODO: add const reference versions
  159.     //
  160.            IEEEfloat  operator+  (IEEEfloat);   // binary addition
  161.     inline IEEEfloat  operator+  (void)         { return *this; } // unary plus
  162.     inline IEEEfloat &operator+= (IEEEfloat op) { return *this = *this + op; } // add and assign
  163.     inline IEEEfloat  operator++ (void)         { return *this += 1; } // pre-increment
  164.     inline IEEEfloat  operator++ (int dummy)
  165.     {
  166.         IEEEfloat result = *this;
  167.         *this += 1;
  168.         return result;
  169.     } // post-increment
  170.  
  171.            IEEEfloat  operator-  (void);        // unary minus
  172.     inline IEEEfloat  operator-  (IEEEfloat op) { return *this + (-op); } // binary subtraction
  173.     inline IEEEfloat &operator-= (IEEEfloat op) { return *this = *this - op; } // subtract and assign
  174.     inline IEEEfloat  operator-- (void)         { return *this -= 1; } // pre-decrement
  175.     inline IEEEfloat  operator-- (int dummy)
  176.     {
  177.         IEEEfloat result = *this;
  178.         *this -= 1;
  179.         return result;
  180.     } // post-decrement
  181.  
  182.            IEEEfloat  operator*  (IEEEfloat);   // multiplication
  183.     inline IEEEfloat &operator*= (IEEEfloat op) { return *this = *this * op; } // multiply and assign
  184.  
  185.            IEEEfloat  operator/  (IEEEfloat);   // divide
  186.     inline IEEEfloat &operator/= (IEEEfloat op) { return *this = *this / op; } // divide and assign
  187.  
  188.            IEEEfloat  operator%  (IEEEfloat);   // modulus
  189.     inline IEEEfloat &operator%= (IEEEfloat op) { return *this = *this % op; } // modulus and assign
  190.  
  191.     //
  192.     // Comparison operators.  Recall that NaN does not compare, and 0.0 == -0.0
  193.     //
  194.     bool operator== (IEEEfloat); // equal
  195.     bool operator!= (IEEEfloat); // not equal
  196.     bool operator<  (IEEEfloat); // less-than
  197.     bool operator>  (IEEEfloat); // greater-than
  198.     bool operator<= (IEEEfloat); // less-than or equal
  199.     bool operator>= (IEEEfloat); // greater-than or equal
  200.  
  201.     //
  202.     // Methods for hashing floats, behave like java.lang.Float counterparts:
  203.     //  * -0.0f and 0.0f are different, with positive 0 comparing as greater
  204.     //    than negative 0.
  205.     //  * identical bit patterns of NaN are the same in equals, but not
  206.     //    unique patterns
  207.     //  * all bit patterns of NaN compare as greater than any other float,
  208.     //    including positive infinity, but the same as any other NaN pattern
  209.     //
  210.     inline bool equals(IEEEfloat op) { return value.word == op.value.word; }
  211.     inline i4 hashCode(void) { return value.iword; }
  212.     inline int compareTo(IEEEfloat op)
  213.     {
  214.         return IsNaN() ? 1
  215.                        : (IsZero() && op.IsZero()) ? op.Sign() - Sign()
  216.                                                    : (*this < op) ? -1
  217.                                                                   : *this > op;
  218.     }        
  219. };
  220.  
  221.  
  222. class IEEEdouble : public BaseLong
  223.     //
  224.     // If HAVE_IEEE754 is defined, this class is simply a wrapper for
  225.     // compiler-supported IEEE operations.  If not, then this class
  226.     // emulates IEEE 754 behavior, in acccordance with the Java Language,
  227.     // using only integer arithmetic.
  228.     //
  229. {
  230. private:
  231.     enum { FRACT_BITS = 52, BIAS = 1023 };
  232.  
  233.     inline u4 SignBit(void) { return HighWord() & 0x80000000; }
  234.     inline u4 ExpBits(void) { return HighWord() & 0x7FF00000; }
  235.  
  236.     // takes the (possibly) unnormalized fraction with its corresponding
  237.     // exponent and sign, and creates the normalized double
  238.     static IEEEdouble Normalize(int, int, ULongInt);
  239.     // takes the double and splits it into a normalized fraction and exponent;
  240.     // the exponent is returned, the parameter fraction is modified
  241.     int SplitInto(BaseLong &fraction);
  242.  
  243.  
  244.  
  245. #ifndef HAVE_MEMBER_CONSTANTS
  246.     // VC++ can't cope with constant class members
  247.     static u4 MAX_FRACT;
  248.     static u4 MAX_FRACT2;
  249.     static i4 MIN_INT;
  250.     static i4 MAX_INT;
  251. #else
  252.     static const u4 MAX_FRACT  = 0x00200000;
  253.     static const u4 MAX_FRACT2 = 0x00100000;
  254.     static const i4 MIN_INT    = 0x80000000;
  255.     static const i4 MAX_INT    = 0x7FFFFFFF;
  256. #endif
  257.  
  258. public:
  259.     //
  260.     // Information methods, for evaluating components of the float
  261.     //
  262.     inline int     Sign(void)     { return HighWord() >> 31; }
  263.     inline int     Exponent(void) { return (int) ((HighWord() >> 20) & 0x000007FF) - BIAS; }
  264.     inline LongInt Fraction(void)
  265.     {
  266.         return LongInt((HighWord() & 0x000FFFFF) | (ExpBits() ? 0x00100000 : 0),
  267.                        LowWord()); 
  268.     }
  269.  
  270.     inline bool IsNaN(void)
  271.     {
  272.         // optimized for no branching, idea from fdlibm.c
  273.         u4 high = HighWord(),
  274.             low = LowWord();
  275.         return ((high & 0x7FFFFFFF) | ((low | -(i4) low) >> 31)) > 0x7FF00000;
  276.     }
  277.  
  278.     inline bool IsNegative(void) { return ((i4) HighWord() < 0) && !IsNaN(); }
  279.     inline bool IsPositive(void) { return ((i4) HighWord() >= 0) && !IsNaN(); }
  280.  
  281.     inline bool IsNegativeZero(void)
  282.     {
  283.         return (HighWord() == 0x80000000) && (LowWord() == 0x00000000);
  284.     }
  285.     inline bool IsPositiveZero(void)
  286.     {
  287.         return (HighWord() == 0x00000000) && (LowWord() == 0x00000000);
  288.     }
  289.     inline bool IsZero(void)
  290.     {
  291.         return ((HighWord() & 0x7FFFFFFF) == 0x00000000) && (LowWord() == 0x00000000);
  292.     }
  293.  
  294.     inline bool IsNegativeInfinity(void)
  295.     {
  296.         return (HighWord() == 0xFFF00000) && (LowWord() == 0x00000000);
  297.     }
  298.     inline bool IsPositiveInfinity(void)
  299.     {
  300.         return (HighWord() == 0x7FF00000) && (LowWord() == 0x00000000);
  301.     }
  302.     inline bool IsInfinite(void)
  303.     {
  304.         return ((HighWord() & 0x7FFFFFFF) == 0x7FF00000) && (LowWord() == 0x00000000);
  305.     }
  306.  
  307.  
  308.     //
  309.     // Generation methods, for creating common constants
  310.     //
  311.     static inline IEEEdouble NaN(void)               { return IEEEdouble(0x7FF80000U, 0x00000000U); }
  312.     static inline IEEEdouble POSITIVE_INFINITY(void) { return IEEEdouble(0x7FF00000U, 0x00000000U); }
  313.     static inline IEEEdouble NEGATIVE_INFINITY(void) { return IEEEdouble(0xFFF00000U, 0x00000000U); }
  314.     static inline IEEEdouble POSITIVE_ZERO(void)     { return IEEEdouble(0x00000000U, 0x00000000U); }
  315.     static inline IEEEdouble NEGATIVE_ZERO(void)     { return IEEEdouble(0x80000000U, 0x00000000U); }
  316.  
  317.  
  318.     //
  319.     // Constructors
  320.     //
  321.     // Create a double from the given value
  322.     inline IEEEdouble(double d) { value.double_value = d; }
  323.     // Convert string to double, the double is NaN if check_invalid is true and input is invalid by JLS
  324.            IEEEdouble(char *, bool check_invalid = false);
  325.  
  326.     // widening conversion of int to double, no information lost
  327.            IEEEdouble(i4);
  328.     // Widening conversion of long to double, may lose precision
  329.            IEEEdouble(LongInt);
  330.     // Widening conversion of float to double, no information lost
  331.            IEEEdouble(IEEEfloat);
  332.     // Create a double without initializing it
  333.     inline IEEEdouble(void) {}
  334.     // Load a specified bit pattern (contrast to IEEEfloat(LongInt))
  335.     inline IEEEdouble(u4 hi, u4 lo) { setHighAndLowWords(hi, lo); }
  336.  
  337.     //
  338.     // Conversion routines
  339.     //
  340.            i4        IntValue(void);
  341.            LongInt   LongValue(void);
  342.     inline IEEEfloat FloatValue(void) { return IEEEfloat(*this); }
  343.  
  344.  
  345.     //
  346.     // Floating-point operations
  347.     // TODO: add const reference versions
  348.     //
  349.            IEEEdouble  operator+  (IEEEdouble);   // binary addition
  350.     inline IEEEdouble  operator+  (void)          { return *this; } // unary plus
  351.     inline IEEEdouble &operator+= (IEEEdouble op) { return *this = *this + op; } // add and assign
  352.     inline IEEEdouble  operator++ (void)          { return *this += 1; } // pre-increment
  353.     inline IEEEdouble  operator++ (int dummy)
  354.     {
  355.         IEEEdouble result = *this;
  356.         *this += 1;
  357.         return result;
  358.     } // post-increment
  359.  
  360.            IEEEdouble  operator-  (void);         // unary minus
  361.     inline IEEEdouble  operator-  (IEEEdouble op) { return *this + (-op); } // binary subtraction
  362.     inline IEEEdouble &operator-= (IEEEdouble op) { return *this = *this - op; } // subtract and assign
  363.     inline IEEEdouble  operator-- (void)          { return *this -= 1; } // pre-decrement
  364.     inline IEEEdouble  operator-- (int dummy)
  365.     {
  366.         IEEEdouble result = *this;
  367.         *this -= 1;
  368.         return result;
  369.     } // post-decrement
  370.  
  371.            IEEEdouble  operator*  (IEEEdouble);   // multiplication
  372.     inline IEEEdouble &operator*= (IEEEdouble op) { return *this = *this * op; } // multiply and assign
  373.  
  374.            IEEEdouble  operator/  (IEEEdouble);   // divide
  375.     inline IEEEdouble &operator/= (IEEEdouble op) { return *this = *this / op; } // divide and assign
  376.  
  377.            IEEEdouble  operator%  (IEEEdouble);   // modulus
  378.     inline IEEEdouble &operator%= (IEEEdouble op) { return *this = *this % op; } // modulus and assign
  379.  
  380.     //
  381.     // Comparison operators.  Recall that NaN does not compare, and 0.0 == -0.0
  382.     //
  383.     bool operator== (IEEEdouble); // equal
  384.     bool operator!= (IEEEdouble); // not equal
  385.     bool operator<  (IEEEdouble); // less-than
  386.     bool operator>  (IEEEdouble); // greater-than
  387.     bool operator<= (IEEEdouble); // less-than or equal
  388.     bool operator>= (IEEEdouble); // greater-than or equal
  389.  
  390.     //
  391.     // Methods for hashing doubles, behave like java.lang.Double counterparts:
  392.     //  * -0.0 and 0.0 are different, with positive 0 comparing as greater
  393.     //    than negative 0.
  394.     //  * identical bit patterns of NaN are the same in equals, but not
  395.     //    unique patterns
  396.     //  * all bit patterns of NaN compare as greater than any other float,
  397.     //    including positive infinity, but the same as any other NaN pattern
  398.     //
  399.     inline bool equals(IEEEdouble op) { return (BaseLong) *this == (BaseLong) op; }
  400.     inline i4 hashCode(void) { return ((BaseLong) *this).hashCode(); }
  401.     inline int compareTo(IEEEdouble op)
  402.     {
  403.         return IsNaN() ? 1
  404.                        : (IsZero() && op.IsZero()) ? op.Sign() - Sign()
  405.                                                    : (*this < op) ? -1
  406.                                                                   : *this > op;
  407.     }        
  408. };
  409.  
  410.  
  411. inline IEEEdouble IEEEfloat::DoubleValue()
  412. {
  413.     return IEEEdouble(*this);
  414. }
  415.  
  416. #ifdef    HAVE_JIKES_NAMESPACE
  417. }            // Close namespace Jikes block
  418. #endif
  419.  
  420. #endif // Double_INCLUDED
  421.  
  422.