mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 20:59:51 +00:00
initial checkin of Neil's APFloat work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41203 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9cf8e5d092
commit
b39cdde41d
258
include/llvm/ADT/APFloat.h
Normal file
258
include/llvm/ADT/APFloat.h
Normal file
@ -0,0 +1,258 @@
|
||||
//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==//
|
||||
//
|
||||
// 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 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 using 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.
|
||||
|
||||
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. 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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
indeterminate and meaningless. For QNaNs the sign bit, as well as
|
||||
the exponent and significand are indeterminate and meaningless.
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
New operations: sqrt, copysign, 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;
|
||||
|
||||
/* 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 IEEEsingle;
|
||||
static const fltSemantics IEEEdouble;
|
||||
static const fltSemantics IEEEquad;
|
||||
static const fltSemantics x87DoubleExtended;
|
||||
|
||||
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,
|
||||
fcQNaN,
|
||||
fcNormal,
|
||||
fcZero
|
||||
};
|
||||
|
||||
/* Constructors. */
|
||||
APFloat(const fltSemantics &, const char *);
|
||||
APFloat(const fltSemantics &, integerPart);
|
||||
APFloat(const fltSemantics &, fltCategory, bool negative);
|
||||
APFloat(const APFloat &);
|
||||
~APFloat();
|
||||
|
||||
/* Arithmetic. */
|
||||
opStatus add(const APFloat &, roundingMode);
|
||||
opStatus subtract(const APFloat &, roundingMode);
|
||||
opStatus multiply(const APFloat &, roundingMode);
|
||||
opStatus divide(const APFloat &, roundingMode);
|
||||
opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode);
|
||||
void changeSign();
|
||||
|
||||
/* Conversions. */
|
||||
opStatus convert(const fltSemantics &, roundingMode);
|
||||
opStatus convertToInteger(integerPart *, unsigned int, bool,
|
||||
roundingMode) const;
|
||||
opStatus convertFromInteger(const integerPart *, unsigned int, bool,
|
||||
roundingMode);
|
||||
opStatus convertFromString(const char *, roundingMode);
|
||||
|
||||
/* Comparison with another floating point number. */
|
||||
cmpResult compare(const APFloat &) 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 isNegative() const { return sign; }
|
||||
|
||||
APFloat& operator=(const APFloat &);
|
||||
|
||||
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 &);
|
||||
|
||||
/* Miscellany. */
|
||||
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);
|
||||
opStatus convertFromHexadecimalString(const char *, roundingMode);
|
||||
|
||||
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. */
|
||||
fltCategory category: 2;
|
||||
|
||||
/* The sign bit of this number. */
|
||||
unsigned int sign: 1;
|
||||
};
|
||||
} /* namespace llvm */
|
||||
|
||||
#endif /* LLVM_FLOAT_H */
|
@ -19,9 +19,7 @@
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#define HOST_CHAR_BIT 8
|
||||
#define compileTimeAssert(cond) extern int CTAssert[(cond) ? 1 : -1]
|
||||
#define integerPartWidth (HOST_CHAR_BIT * sizeof(llvm::integerPart))
|
||||
#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1]
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -29,6 +27,9 @@ namespace llvm {
|
||||
bignum. */
|
||||
typedef uint64_t integerPart;
|
||||
|
||||
const unsigned int host_char_bit = 8;
|
||||
const unsigned int integerPartWidth = host_char_bit * sizeof(integerPart);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APInt Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
1488
lib/Support/APFloat.cpp
Normal file
1488
lib/Support/APFloat.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -2018,19 +2018,39 @@ void APInt::dump() const
|
||||
|
||||
/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe
|
||||
and unrestricting assumption. */
|
||||
compileTimeAssert(integerPartWidth % 2 == 0);
|
||||
|
||||
#define lowBitMask(bits) (~(integerPart) 0 >> (integerPartWidth - (bits)))
|
||||
#define lowHalf(part) ((part) & lowBitMask(integerPartWidth / 2))
|
||||
#define highHalf(part) ((part) >> (integerPartWidth / 2))
|
||||
COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0);
|
||||
|
||||
/* Some handy functions local to this file. */
|
||||
namespace {
|
||||
|
||||
/* Returns the integer part with the least significant BITS set.
|
||||
BITS cannot be zero. */
|
||||
inline integerPart
|
||||
lowBitMask(unsigned int bits)
|
||||
{
|
||||
assert (bits != 0 && bits <= integerPartWidth);
|
||||
|
||||
return ~(integerPart) 0 >> (integerPartWidth - bits);
|
||||
}
|
||||
|
||||
/* Returns the value of the lower nibble of PART. */
|
||||
inline integerPart
|
||||
lowHalf(integerPart part)
|
||||
{
|
||||
return part & lowBitMask(integerPartWidth / 2);
|
||||
}
|
||||
|
||||
/* Returns the value of the upper nibble of PART. */
|
||||
inline integerPart
|
||||
highHalf(integerPart part)
|
||||
{
|
||||
return part >> (integerPartWidth / 2);
|
||||
}
|
||||
|
||||
/* Returns the bit number of the most significant bit of a part. If
|
||||
the input number has no bits set -1U is returned. */
|
||||
unsigned int
|
||||
PartMSB(integerPart value)
|
||||
partMSB(integerPart value)
|
||||
{
|
||||
unsigned int n, msb;
|
||||
|
||||
@ -2157,7 +2177,7 @@ APInt::tcMSB(const integerPart *parts, unsigned int n)
|
||||
--n;
|
||||
|
||||
if (parts[n] != 0) {
|
||||
msb = PartMSB(parts[n]);
|
||||
msb = partMSB(parts[n]);
|
||||
|
||||
return msb + n * integerPartWidth;
|
||||
}
|
||||
@ -2388,11 +2408,11 @@ APInt::tcDivide(integerPart *lhs, const integerPart *rhs,
|
||||
|
||||
assert(lhs != remainder && lhs != srhs && remainder != srhs);
|
||||
|
||||
shiftCount = tcMSB(rhs, parts);
|
||||
if (shiftCount == -1U)
|
||||
shiftCount = tcMSB(rhs, parts) + 1;
|
||||
if (shiftCount == 0)
|
||||
return true;
|
||||
|
||||
shiftCount = parts * integerPartWidth - shiftCount - 1;
|
||||
shiftCount = parts * integerPartWidth - shiftCount;
|
||||
n = shiftCount / integerPartWidth;
|
||||
mask = (integerPart) 1 << (shiftCount % integerPartWidth);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user