mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	major bugs in long-precision conversion. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92150 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			420 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			420 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file declares a class to represent arbitrary precision floating
 | |
| // point values and provide a variety of arithmetic operations on them.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| /*  A self-contained host- and target-independent arbitrary-precision
 | |
|     floating-point software implementation.  It uses bignum integer
 | |
|     arithmetic as provided by static functions in the APInt class.
 | |
|     The library will work with bignum integers whose parts are any
 | |
|     unsigned type at least 16 bits wide, but 64 bits is recommended.
 | |
| 
 | |
|     Written for clarity rather than speed, in particular with a view
 | |
|     to use in the front-end of a cross compiler so that target
 | |
|     arithmetic can be correctly performed on the host.  Performance
 | |
|     should nonetheless be reasonable, particularly for its intended
 | |
|     use.  It may be useful as a base implementation for a run-time
 | |
|     library during development of a faster target-specific one.
 | |
| 
 | |
|     All 5 rounding modes in the IEEE-754R draft are handled correctly
 | |
|     for all implemented operations.  Currently implemented operations
 | |
|     are add, subtract, multiply, divide, fused-multiply-add,
 | |
|     conversion-to-float, conversion-to-integer and
 | |
|     conversion-from-integer.  New rounding modes (e.g. away from zero)
 | |
|     can be added with three or four lines of code.
 | |
| 
 | |
|     Four formats are built-in: IEEE single precision, double
 | |
|     precision, quadruple precision, and x87 80-bit extended double
 | |
|     (when operating with full extended precision).  Adding a new
 | |
|     format that obeys IEEE semantics only requires adding two lines of
 | |
|     code: a declaration and definition of the format.
 | |
| 
 | |
|     All operations return the status of that operation as an exception
 | |
|     bit-mask, so multiple operations can be done consecutively with
 | |
|     their results or-ed together.  The returned status can be useful
 | |
|     for compiler diagnostics; e.g., inexact, underflow and overflow
 | |
|     can be easily diagnosed on constant folding, and compiler
 | |
|     optimizers can determine what exceptions would be raised by
 | |
|     folding operations and optimize, or perhaps not optimize,
 | |
|     accordingly.
 | |
| 
 | |
|     At present, underflow tininess is detected after rounding; it
 | |
|     should be straight forward to add support for the before-rounding
 | |
|     case too.
 | |
| 
 | |
|     The library reads hexadecimal floating point numbers as per C99,
 | |
|     and correctly rounds if necessary according to the specified
 | |
|     rounding mode.  Syntax is required to have been validated by the
 | |
|     caller.  It also converts floating point numbers to hexadecimal
 | |
|     text as per the C99 %a and %A conversions.  The output precision
 | |
|     (or alternatively the natural minimal precision) can be specified;
 | |
|     if the requested precision is less than the natural precision the
 | |
|     output is correctly rounded for the specified rounding mode.
 | |
| 
 | |
|     It also reads decimal floating point numbers and correctly rounds
 | |
|     according to the specified rounding mode.
 | |
| 
 | |
|     Conversion to decimal text is not currently implemented.
 | |
| 
 | |
|     Non-zero finite numbers are represented internally as a sign bit,
 | |
|     a 16-bit signed exponent, and the significand as an array of
 | |
|     integer parts.  After normalization of a number of precision P the
 | |
|     exponent is within the range of the format, and if the number is
 | |
|     not denormal the P-th bit of the significand is set as an explicit
 | |
|     integer bit.  For denormals the most significant bit is shifted
 | |
|     right so that the exponent is maintained at the format's minimum,
 | |
|     so that the smallest denormal has just the least significant bit
 | |
|     of the significand set.  The sign of zeroes and infinities is
 | |
|     significant; the exponent and significand of such numbers is not
 | |
|     stored, but has a known implicit (deterministic) value: 0 for the
 | |
|     significands, 0 for zero exponent, all 1 bits for infinity
 | |
|     exponent.  For NaNs the sign and significand are deterministic,
 | |
|     although not really meaningful, and preserved in non-conversion
 | |
|     operations.  The exponent is implicitly all 1 bits.
 | |
| 
 | |
|     TODO
 | |
|     ====
 | |
| 
 | |
|     Some features that may or may not be worth adding:
 | |
| 
 | |
|     Binary to decimal conversion (hard).
 | |
| 
 | |
|     Optional ability to detect underflow tininess before rounding.
 | |
| 
 | |
|     New formats: x87 in single and double precision mode (IEEE apart
 | |
|     from extended exponent range) (hard).
 | |
| 
 | |
|     New operations: sqrt, IEEE remainder, C90 fmod, nextafter,
 | |
|     nexttoward.
 | |
| */
 | |
| 
 | |
| #ifndef LLVM_FLOAT_H
 | |
| #define LLVM_FLOAT_H
 | |
| 
 | |
| // APInt contains static functions implementing bignum arithmetic.
 | |
| #include "llvm/ADT/APInt.h"
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
|   /* Exponents are stored as signed numbers.  */
 | |
|   typedef signed short exponent_t;
 | |
| 
 | |
|   struct fltSemantics;
 | |
|   class StringRef;
 | |
| 
 | |
|   /* When bits of a floating point number are truncated, this enum is
 | |
|      used to indicate what fraction of the LSB those bits represented.
 | |
|      It essentially combines the roles of guard and sticky bits.  */
 | |
|   enum lostFraction {           // Example of truncated bits:
 | |
|     lfExactlyZero,              // 000000
 | |
|     lfLessThanHalf,             // 0xxxxx  x's not all zero
 | |
|     lfExactlyHalf,              // 100000
 | |
|     lfMoreThanHalf              // 1xxxxx  x's not all zero
 | |
|   };
 | |
| 
 | |
|   class APFloat {
 | |
|   public:
 | |
| 
 | |
|     /* We support the following floating point semantics.  */
 | |
|     static const fltSemantics IEEEhalf;
 | |
|     static const fltSemantics IEEEsingle;
 | |
|     static const fltSemantics IEEEdouble;
 | |
|     static const fltSemantics IEEEquad;
 | |
|     static const fltSemantics PPCDoubleDouble;
 | |
|     static const fltSemantics x87DoubleExtended;
 | |
|     /* And this pseudo, used to construct APFloats that cannot
 | |
|        conflict with anything real. */
 | |
|     static const fltSemantics Bogus;
 | |
| 
 | |
|     static unsigned int semanticsPrecision(const fltSemantics &);
 | |
| 
 | |
|     /* Floating point numbers have a four-state comparison relation.  */
 | |
|     enum cmpResult {
 | |
|       cmpLessThan,
 | |
|       cmpEqual,
 | |
|       cmpGreaterThan,
 | |
|       cmpUnordered
 | |
|     };
 | |
| 
 | |
|     /* IEEE-754R gives five rounding modes.  */
 | |
|     enum roundingMode {
 | |
|       rmNearestTiesToEven,
 | |
|       rmTowardPositive,
 | |
|       rmTowardNegative,
 | |
|       rmTowardZero,
 | |
|       rmNearestTiesToAway
 | |
|     };
 | |
| 
 | |
|     // Operation status.  opUnderflow or opOverflow are always returned
 | |
|     // or-ed with opInexact.
 | |
|     enum opStatus {
 | |
|       opOK          = 0x00,
 | |
|       opInvalidOp   = 0x01,
 | |
|       opDivByZero   = 0x02,
 | |
|       opOverflow    = 0x04,
 | |
|       opUnderflow   = 0x08,
 | |
|       opInexact     = 0x10
 | |
|     };
 | |
| 
 | |
|     // Category of internally-represented number.
 | |
|     enum fltCategory {
 | |
|       fcInfinity,
 | |
|       fcNaN,
 | |
|       fcNormal,
 | |
|       fcZero
 | |
|     };
 | |
| 
 | |
|     // Constructors.
 | |
|     APFloat(const fltSemantics &); // Default construct to 0.0
 | |
|     APFloat(const fltSemantics &, const StringRef &);
 | |
|     APFloat(const fltSemantics &, integerPart);
 | |
|     APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0);
 | |
|     explicit APFloat(double d);
 | |
|     explicit APFloat(float f);
 | |
|     explicit APFloat(const APInt &, bool isIEEE = false);
 | |
|     APFloat(const APFloat &);
 | |
|     ~APFloat();
 | |
| 
 | |
|     // Convenience "constructors"
 | |
|     static APFloat getZero(const fltSemantics &Sem, bool Negative = false) {
 | |
|       return APFloat(Sem, fcZero, Negative);
 | |
|     }
 | |
|     static APFloat getInf(const fltSemantics &Sem, bool Negative = false) {
 | |
|       return APFloat(Sem, fcInfinity, Negative);
 | |
|     }
 | |
| 
 | |
|     /// getNaN - Factory for QNaN values.
 | |
|     ///
 | |
|     /// \param Negative - True iff the NaN generated should be negative.
 | |
|     /// \param type - The unspecified fill bits for creating the NaN, 0 by
 | |
|     /// default.  The value is truncated as necessary.
 | |
|     static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
 | |
|                           unsigned type = 0) {
 | |
|       return APFloat(Sem, fcNaN, Negative, type);
 | |
|     }
 | |
| 
 | |
|     /// getLargest - Returns the largest finite number in the given
 | |
|     /// semantics.
 | |
|     ///
 | |
|     /// \param Negative - True iff the number should be negative
 | |
|     static APFloat getLargest(const fltSemantics &Sem, bool Negative = false);
 | |
| 
 | |
|     /// getSmallest - Returns the smallest (by magnitude) finite number
 | |
|     /// in the given semantics.  Might be denormalized, which implies a
 | |
|     /// relative loss of precision.
 | |
|     ///
 | |
|     /// \param Negative - True iff the number should be negative
 | |
|     static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false);
 | |
| 
 | |
|     /// getSmallestNormalized - Returns the smallest (by magnitude)
 | |
|     /// normalized finite number in the given semantics.
 | |
|     ///
 | |
|     /// \param Negative - True iff the number should be negative
 | |
|     static APFloat getSmallestNormalized(const fltSemantics &Sem,
 | |
|                                          bool Negative = false);
 | |
| 
 | |
|     /// Profile - Used to insert APFloat objects, or objects that contain
 | |
|     ///  APFloat objects, into FoldingSets.
 | |
|     void Profile(FoldingSetNodeID& NID) const;
 | |
| 
 | |
|     /// @brief Used by the Bitcode serializer to emit APInts to Bitcode.
 | |
|     void Emit(Serializer& S) const;
 | |
| 
 | |
|     /// @brief Used by the Bitcode deserializer to deserialize APInts.
 | |
|     static APFloat ReadVal(Deserializer& D);
 | |
| 
 | |
|     /* Arithmetic.  */
 | |
|     opStatus add(const APFloat &, roundingMode);
 | |
|     opStatus subtract(const APFloat &, roundingMode);
 | |
|     opStatus multiply(const APFloat &, roundingMode);
 | |
|     opStatus divide(const APFloat &, roundingMode);
 | |
|     /* IEEE remainder. */
 | |
|     opStatus remainder(const APFloat &);
 | |
|     /* C fmod, or llvm frem. */
 | |
|     opStatus mod(const APFloat &, roundingMode);
 | |
|     opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode);
 | |
| 
 | |
|     /* Sign operations.  */
 | |
|     void changeSign();
 | |
|     void clearSign();
 | |
|     void copySign(const APFloat &);
 | |
| 
 | |
|     /* Conversions.  */
 | |
|     opStatus convert(const fltSemantics &, roundingMode, bool *);
 | |
|     opStatus convertToInteger(integerPart *, unsigned int, bool,
 | |
|                               roundingMode, bool *) const;
 | |
|     opStatus convertFromAPInt(const APInt &,
 | |
|                               bool, roundingMode);
 | |
|     opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
 | |
|                                             bool, roundingMode);
 | |
|     opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
 | |
|                                             bool, roundingMode);
 | |
|     opStatus convertFromString(const StringRef&, roundingMode);
 | |
|     APInt bitcastToAPInt() const;
 | |
|     double convertToDouble() const;
 | |
|     float convertToFloat() const;
 | |
| 
 | |
|     /* The definition of equality is not straightforward for floating point,
 | |
|        so we won't use operator==.  Use one of the following, or write
 | |
|        whatever it is you really mean. */
 | |
|     // bool operator==(const APFloat &) const;     // DO NOT IMPLEMENT
 | |
| 
 | |
|     /* IEEE comparison with another floating point number (NaNs
 | |
|        compare unordered, 0==-0). */
 | |
|     cmpResult compare(const APFloat &) const;
 | |
| 
 | |
|     /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */
 | |
|     bool bitwiseIsEqual(const APFloat &) const;
 | |
| 
 | |
|     /* Write out a hexadecimal representation of the floating point
 | |
|        value to DST, which must be of sufficient size, in the C99 form
 | |
|        [-]0xh.hhhhp[+-]d.  Return the number of characters written,
 | |
|        excluding the terminating NUL.  */
 | |
|     unsigned int convertToHexString(char *dst, unsigned int hexDigits,
 | |
|                                     bool upperCase, roundingMode) const;
 | |
| 
 | |
|     /* Simple queries.  */
 | |
|     fltCategory getCategory() const { return category; }
 | |
|     const fltSemantics &getSemantics() const { return *semantics; }
 | |
|     bool isZero() const { return category == fcZero; }
 | |
|     bool isNonZero() const { return category != fcZero; }
 | |
|     bool isNaN() const { return category == fcNaN; }
 | |
|     bool isInfinity() const { return category == fcInfinity; }
 | |
|     bool isNegative() const { return sign; }
 | |
|     bool isPosZero() const { return isZero() && !isNegative(); }
 | |
|     bool isNegZero() const { return isZero() && isNegative(); }
 | |
| 
 | |
|     APFloat& operator=(const APFloat &);
 | |
| 
 | |
|     /* Return an arbitrary integer value usable for hashing. */
 | |
|     uint32_t getHashValue() const;
 | |
| 
 | |
|     /// Converts this value into a decimal string.
 | |
|     ///
 | |
|     /// \param FormatPrecision The maximum number of digits of
 | |
|     ///   precision to output.  If there are fewer digits available,
 | |
|     ///   zero padding will not be used unless the value is
 | |
|     ///   integral and small enough to be expressed in
 | |
|     ///   FormatPrecision digits.  0 means to use the natural
 | |
|     ///   precision of the number.
 | |
|     /// \param FormatMaxPadding The maximum number of zeros to
 | |
|     ///   consider inserting before falling back to scientific
 | |
|     ///   notation.  0 means to always use scientific notation.
 | |
|     ///
 | |
|     /// Number       Precision    MaxPadding      Result
 | |
|     /// ------       ---------    ----------      ------
 | |
|     /// 1.01E+4              5             2       10100
 | |
|     /// 1.01E+4              4             2       1.01E+4
 | |
|     /// 1.01E+4              5             1       1.01E+4
 | |
|     /// 1.01E-2              5             2       0.0101
 | |
|     /// 1.01E-2              4             2       0.0101
 | |
|     /// 1.01E-2              4             1       1.01E-2
 | |
|     void toString(SmallVectorImpl<char> &Str,
 | |
|                   unsigned FormatPrecision = 0,
 | |
|                   unsigned FormatMaxPadding = 3);
 | |
| 
 | |
|   private:
 | |
| 
 | |
|     /* Trivial queries.  */
 | |
|     integerPart *significandParts();
 | |
|     const integerPart *significandParts() const;
 | |
|     unsigned int partCount() const;
 | |
| 
 | |
|     /* Significand operations.  */
 | |
|     integerPart addSignificand(const APFloat &);
 | |
|     integerPart subtractSignificand(const APFloat &, integerPart);
 | |
|     lostFraction addOrSubtractSignificand(const APFloat &, bool subtract);
 | |
|     lostFraction multiplySignificand(const APFloat &, const APFloat *);
 | |
|     lostFraction divideSignificand(const APFloat &);
 | |
|     void incrementSignificand();
 | |
|     void initialize(const fltSemantics *);
 | |
|     void shiftSignificandLeft(unsigned int);
 | |
|     lostFraction shiftSignificandRight(unsigned int);
 | |
|     unsigned int significandLSB() const;
 | |
|     unsigned int significandMSB() const;
 | |
|     void zeroSignificand();
 | |
| 
 | |
|     /* Arithmetic on special values.  */
 | |
|     opStatus addOrSubtractSpecials(const APFloat &, bool subtract);
 | |
|     opStatus divideSpecials(const APFloat &);
 | |
|     opStatus multiplySpecials(const APFloat &);
 | |
|     opStatus modSpecials(const APFloat &);
 | |
| 
 | |
|     /* Miscellany.  */
 | |
|     void makeNaN(unsigned = 0);
 | |
|     opStatus normalize(roundingMode, lostFraction);
 | |
|     opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
 | |
|     cmpResult compareAbsoluteValue(const APFloat &) const;
 | |
|     opStatus handleOverflow(roundingMode);
 | |
|     bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
 | |
|     opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
 | |
|                                           roundingMode, bool *) const;
 | |
|     opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
 | |
|                                       roundingMode);
 | |
|     opStatus convertFromHexadecimalString(const StringRef&, roundingMode);
 | |
|     opStatus convertFromDecimalString (const StringRef&, roundingMode);
 | |
|     char *convertNormalToHexString(char *, unsigned int, bool,
 | |
|                                    roundingMode) const;
 | |
|     opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
 | |
|                                           int, roundingMode);
 | |
| 
 | |
|     APInt convertHalfAPFloatToAPInt() const;
 | |
|     APInt convertFloatAPFloatToAPInt() const;
 | |
|     APInt convertDoubleAPFloatToAPInt() const;
 | |
|     APInt convertQuadrupleAPFloatToAPInt() const;
 | |
|     APInt convertF80LongDoubleAPFloatToAPInt() const;
 | |
|     APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
 | |
|     void initFromAPInt(const APInt& api, bool isIEEE = false);
 | |
|     void initFromHalfAPInt(const APInt& api);
 | |
|     void initFromFloatAPInt(const APInt& api);
 | |
|     void initFromDoubleAPInt(const APInt& api);
 | |
|     void initFromQuadrupleAPInt(const APInt &api);
 | |
|     void initFromF80LongDoubleAPInt(const APInt& api);
 | |
|     void initFromPPCDoubleDoubleAPInt(const APInt& api);
 | |
| 
 | |
|     void assign(const APFloat &);
 | |
|     void copySignificand(const APFloat &);
 | |
|     void freeSignificand();
 | |
| 
 | |
|     /* What kind of semantics does this value obey?  */
 | |
|     const fltSemantics *semantics;
 | |
| 
 | |
|     /* Significand - the fraction with an explicit integer bit.  Must be
 | |
|        at least one bit wider than the target precision.  */
 | |
|     union Significand
 | |
|     {
 | |
|       integerPart part;
 | |
|       integerPart *parts;
 | |
|     } significand;
 | |
| 
 | |
|     /* The exponent - a signed number.  */
 | |
|     exponent_t exponent;
 | |
| 
 | |
|     /* What kind of floating point number this is.  */
 | |
|     /* Only 2 bits are required, but VisualStudio incorrectly sign extends
 | |
|        it.  Using the extra bit keeps it from failing under VisualStudio */
 | |
|     fltCategory category: 3;
 | |
| 
 | |
|     /* The sign bit of this number.  */
 | |
|     unsigned int sign: 1;
 | |
| 
 | |
|     /* For PPCDoubleDouble, we have a second exponent and sign (the second
 | |
|        significand is appended to the first one, although it would be wrong to
 | |
|        regard these as a single number for arithmetic purposes).  These fields
 | |
|        are not meaningful for any other type. */
 | |
|     exponent_t exponent2 : 11;
 | |
|     unsigned int sign2: 1;
 | |
|   };
 | |
| } /* namespace llvm */
 | |
| 
 | |
| #endif /* LLVM_FLOAT_H */
 |