//===----------------------------------------------------------------------===//
/* 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
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
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
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
// APInt contains static functions implementing bignum arithmetic.
#include "llvm/ADT/APInt.h"
+#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/CodeGen/ValueTypes.h"
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
conflict with anything real. */
APFloat(const fltSemantics &, fltCategory, bool negative);
explicit APFloat(double d);
explicit APFloat(float f);
- explicit APFloat(const APInt &);
+ explicit APFloat(const APInt &, bool isIEEE = false);
APFloat(const APFloat &);
~APFloat();
+
+ /// @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 multiply(const APFloat &, roundingMode);
opStatus divide(const APFloat &, roundingMode);
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 convertToInteger(integerPart *, unsigned int, bool,
roundingMode) const;
- opStatus convertFromInteger(const integerPart *, unsigned int, 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;
double convertToDouble() const;
compare unordered, 0==-0). */
cmpResult compare(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;
+
/* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */
bool bitwiseIsEqual(const APFloat &) const;
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 isNegative() const { return sign; }
bool isPosZero() const { return isZero() && !isNegative(); }
bool isNegZero() const { return isZero() && isNegative(); }
opStatus multiplySpecials(const APFloat &);
/* Miscellany. */
+ void makeNaN(void);
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 convertFromUnsignedInteger(integerPart *, unsigned int,
- roundingMode);
- lostFraction combineLostFractions(lostFraction, lostFraction);
+ opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
+ roundingMode) 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 &);
/* 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 */