X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FAPFloat.h;h=928ecc0c3cf579e3df588f8c1cdcd9823deec403;hb=aafa94260d5b1b6422258ed3db7244fe4449f217;hp=69d1e123ef34c379a3a7867251e6e797eeb7802a;hpb=117acf9e36a0789d56b52525e031f575f80fe169;p=oota-llvm.git diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 69d1e123ef3..928ecc0c3cf 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Neil Booth and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -13,10 +13,10 @@ //===----------------------------------------------------------------------===// /* A self-contained host- and target-independent arbitrary-precision - floating-point software implementation using bignum integer - arithmetic, as provided by static functions in the APInt class. + 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. 64 bits is recommended. + 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 @@ -30,10 +30,7 @@ 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. The library reads - and correctly rounds hexadecimal floating point numbers as per - C99; syntax is required to have been validated by the caller. - Conversion from decimal is not currently implemented. + 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 @@ -54,6 +51,20 @@ 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 @@ -75,19 +86,15 @@ Some features that may or may not be worth adding: - Conversions to and from decimal strings (hard). - - Conversions to hexadecimal string. - - Read and write IEEE-format in-memory representations. + 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) and IBM two-double extended - precision (hard). + from extended exponent range) (hard). - New operations: sqrt, nextafter, nexttoward. + New operations: sqrt, IEEE remainder, C90 fmod, nextafter, + nexttoward. */ #ifndef LLVM_FLOAT_H @@ -95,7 +102,6 @@ // APInt contains static functions implementing bignum arithmetic. #include "llvm/ADT/APInt.h" -#include "llvm/CodeGen/ValueTypes.h" namespace llvm { @@ -107,11 +113,11 @@ namespace llvm { /* 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 + 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 { @@ -121,8 +127,9 @@ namespace llvm { static const fltSemantics IEEEsingle; static const fltSemantics IEEEdouble; static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; static const fltSemantics x87DoubleExtended; - /* And this psuedo, used to construct APFloats that cannot + /* And this pseudo, used to construct APFloats that cannot conflict with anything real. */ static const fltSemantics Bogus; @@ -145,8 +152,8 @@ namespace llvm { rmNearestTiesToAway }; - /* Operation status. opUnderflow or opOverflow are always returned - or-ed with opInexact. */ + // Operation status. opUnderflow or opOverflow are always returned + // or-ed with opInexact. enum opStatus { opOK = 0x00, opInvalidOp = 0x01, @@ -156,7 +163,7 @@ namespace llvm { opInexact = 0x10 }; - /* Category of internally-represented number. */ + // Category of internally-represented number. enum fltCategory { fcInfinity, fcNaN, @@ -164,35 +171,71 @@ namespace llvm { fcZero }; - /* Constructors. */ + // Constructors. APFloat(const fltSemantics &, const char *); APFloat(const fltSemantics &, integerPart); - APFloat(const fltSemantics &, fltCategory, bool negative); + APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0); explicit APFloat(double d); explicit APFloat(float f); - explicit APFloat(const APInt &); + 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); + } + + /// 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); - void copySign(const APFloat &); opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); - void changeSign(); // neg - void clearSign(); // abs + + /* Sign operations. */ + void changeSign(); + void clearSign(); + void copySign(const APFloat &); /* Conversions. */ - opStatus convert(const fltSemantics &, roundingMode); + opStatus convert(const fltSemantics &, roundingMode, bool *); opStatus convertToInteger(integerPart *, unsigned int, bool, - roundingMode) const; - opStatus convertFromInteger(const integerPart *, unsigned int, bool, - roundingMode); + 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 char *, roundingMode); - APInt convertToAPInt() const; + APInt bitcastToAPInt() const; double convertToDouble() const; float convertToFloat() const; @@ -208,11 +251,20 @@ namespace llvm { /* 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(); } @@ -247,24 +299,35 @@ namespace llvm { 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); - opStatus convertFromUnsignedInteger(integerPart *, unsigned int, - roundingMode); - lostFraction combineLostFractions(lostFraction, lostFraction); + 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 char *, roundingMode); + opStatus convertFromDecimalString (const char *, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, + int, roundingMode); + APInt convertFloatAPFloatToAPInt() const; APInt convertDoubleAPFloatToAPInt() const; APInt convertF80LongDoubleAPFloatToAPInt() const; - void initFromAPInt(const APInt& api); + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const APInt& api, bool isIEEE = false); void initFromFloatAPInt(const APInt& api); void initFromDoubleAPInt(const APInt& api); void initFromF80LongDoubleAPInt(const APInt& api); + void initFromPPCDoubleDoubleAPInt(const APInt& api); void assign(const APFloat &); void copySignificand(const APFloat &); @@ -291,6 +354,13 @@ namespace llvm { /* 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 */