Enhance APFloat to retain bits of NaNs (fixes oggenc).
[oota-llvm.git] / include / llvm / ADT / APFloat.h
1 //== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Neil Booth and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares a class to represent arbitrary precision floating
11 // point values and provide a variety of arithmetic operations on them.
12 //
13 //===----------------------------------------------------------------------===//
14
15 /*  A self-contained host- and target-independent arbitrary-precision
16     floating-point software implementation using bignum integer
17     arithmetic, as provided by static functions in the APInt class.
18     The library will work with bignum integers whose parts are any
19     unsigned type at least 16 bits wide.  64 bits is recommended.
20
21     Written for clarity rather than speed, in particular with a view
22     to use in the front-end of a cross compiler so that target
23     arithmetic can be correctly performed on the host.  Performance
24     should nonetheless be reasonable, particularly for its intended
25     use.  It may be useful as a base implementation for a run-time
26     library during development of a faster target-specific one.
27
28     All 5 rounding modes in the IEEE-754R draft are handled correctly
29     for all implemented operations.  Currently implemented operations
30     are add, subtract, multiply, divide, fused-multiply-add,
31     conversion-to-float, conversion-to-integer and
32     conversion-from-integer.  New rounding modes (e.g. away from zero)
33     can be added with three or four lines of code.  The library reads
34     and correctly rounds hexadecimal floating point numbers as per
35     C99; syntax is required to have been validated by the caller.
36     Conversion from decimal is not currently implemented.
37
38     Four formats are built-in: IEEE single precision, double
39     precision, quadruple precision, and x87 80-bit extended double
40     (when operating with full extended precision).  Adding a new
41     format that obeys IEEE semantics only requires adding two lines of
42     code: a declaration and definition of the format.
43
44     All operations return the status of that operation as an exception
45     bit-mask, so multiple operations can be done consecutively with
46     their results or-ed together.  The returned status can be useful
47     for compiler diagnostics; e.g., inexact, underflow and overflow
48     can be easily diagnosed on constant folding, and compiler
49     optimizers can determine what exceptions would be raised by
50     folding operations and optimize, or perhaps not optimize,
51     accordingly.
52
53     At present, underflow tininess is detected after rounding; it
54     should be straight forward to add support for the before-rounding
55     case too.
56
57     Non-zero finite numbers are represented internally as a sign bit,
58     a 16-bit signed exponent, and the significand as an array of
59     integer parts.  After normalization of a number of precision P the
60     exponent is within the range of the format, and if the number is
61     not denormal the P-th bit of the significand is set as an explicit
62     integer bit.  For denormals the most significant bit is shifted
63     right so that the exponent is maintained at the format's minimum,
64     so that the smallest denormal has just the least significant bit
65     of the significand set.  The sign of zeroes and infinities is
66     significant; the exponent and significand of such numbers is
67     not stored, but has a known implicit (deterministic) value:
68     0 for the significands, 0 for zero exponent, all 1 bits for 
69     infinity exponent.  For NaNs the sign and significand are 
70     deterministic, although not really meaningful; the exponent is
71     implicitly all 1 bits.
72
73     TODO
74     ====
75
76     Some features that may or may not be worth adding:
77
78     Conversions to and from decimal strings (hard).
79
80     Conversions to hexadecimal string.
81
82     Read and write IEEE-format in-memory representations.
83
84     Optional ability to detect underflow tininess before rounding.
85
86     New formats: x87 in single and double precision mode (IEEE apart
87     from extended exponent range) and IBM two-double extended
88     precision (hard).
89
90     New operations: sqrt, copysign, nextafter, nexttoward.
91 */
92
93 #ifndef LLVM_FLOAT_H
94 #define LLVM_FLOAT_H
95
96 // APInt contains static functions implementing bignum arithmetic.
97 #include "llvm/ADT/APInt.h"
98
99 namespace llvm {
100
101   /* Exponents are stored as signed numbers.  */
102   typedef signed short exponent_t;
103
104   struct fltSemantics;
105
106   /* When bits of a floating point number are truncated, this enum is
107      used to indicate what fraction of the LSB those bits represented.
108      It essentially combines the roles of guard and sticky bits.  */
109   enum lostFraction {           // Example of truncated bits:
110     lfExactlyZero,              // 000000
111     lfLessThanHalf,             // 0xxxxx  x's not all zero
112     lfExactlyHalf,              // 100000
113     lfMoreThanHalf              // 1xxxxx  x's not all zero
114   };
115
116   class APFloat {
117   public:
118
119     /* We support the following floating point semantics.  */
120     static const fltSemantics IEEEsingle;
121     static const fltSemantics IEEEdouble;
122     static const fltSemantics IEEEquad;
123     static const fltSemantics x87DoubleExtended;
124     /* And this psuedo, used to construct APFloats that cannot
125        conflict with anything real. */
126     static const fltSemantics Bogus;
127
128     static unsigned int semanticsPrecision(const fltSemantics &);
129
130     /* Floating point numbers have a four-state comparison relation.  */
131     enum cmpResult {
132       cmpLessThan,
133       cmpEqual,
134       cmpGreaterThan,
135       cmpUnordered
136     };
137
138     /* IEEE-754R gives five rounding modes.  */
139     enum roundingMode {
140       rmNearestTiesToEven,
141       rmTowardPositive,
142       rmTowardNegative,
143       rmTowardZero,
144       rmNearestTiesToAway
145     };
146
147     /* Operation status.  opUnderflow or opOverflow are always returned
148        or-ed with opInexact.  */
149     enum opStatus {
150       opOK          = 0x00,
151       opInvalidOp   = 0x01,
152       opDivByZero   = 0x02,
153       opOverflow    = 0x04,
154       opUnderflow   = 0x08,
155       opInexact     = 0x10
156     };
157
158     /* Category of internally-represented number.  */
159     enum fltCategory {
160       fcInfinity,
161       fcNaN,
162       fcNormal,
163       fcZero
164     };
165
166     /* Constructors.  */
167     APFloat(const fltSemantics &, const char *);
168     APFloat(const fltSemantics &, integerPart);
169     APFloat(const fltSemantics &, fltCategory, bool negative);
170     APFloat(double d);
171     APFloat(float f);
172     APFloat(const APFloat &);
173     ~APFloat();
174
175     /* Arithmetic.  */
176     opStatus add(const APFloat &, roundingMode);
177     opStatus subtract(const APFloat &, roundingMode);
178     opStatus multiply(const APFloat &, roundingMode);
179     opStatus divide(const APFloat &, roundingMode);
180     opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode);
181     void changeSign();
182
183     /* Conversions.  */
184     opStatus convert(const fltSemantics &, roundingMode);
185     opStatus convertToInteger(integerPart *, unsigned int, bool,
186                               roundingMode) const;
187     opStatus convertFromInteger(const integerPart *, unsigned int, bool,
188                                 roundingMode);
189     opStatus convertFromString(const char *, roundingMode);
190     double convertToDouble() const;
191     float convertToFloat() const;
192
193     /* The definition of equality is not straightforward for floating point,
194        so we won't use operator==.  Use one of the following, or write
195        whatever it is you really mean. */
196     // bool operator==(const APFloat &) const;     // DO NOT IMPLEMENT
197     
198     /* IEEE comparison with another floating point number (NaNs
199        compare unordered, 0==-0). */
200     cmpResult compare(const APFloat &) const;
201
202     /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */
203     bool bitwiseIsEqual(const APFloat &) const;
204
205     /* Simple queries.  */
206     fltCategory getCategory() const { return category; }
207     const fltSemantics &getSemantics() const { return *semantics; }
208     bool isZero() const { return category == fcZero; }
209     bool isNonZero() const { return category != fcZero; }
210     bool isNegative() const { return sign; }
211     bool isPosZero() const { return isZero() && !isNegative(); }
212     bool isNegZero() const { return isZero() && isNegative(); }
213
214     APFloat& operator=(const APFloat &);
215
216     /* Return an arbitrary integer value usable for hashing. */
217     uint32_t getHashValue() const;
218
219   private:
220
221     /* Trivial queries.  */
222     integerPart *significandParts();
223     const integerPart *significandParts() const;
224     unsigned int partCount() const;
225
226     /* Significand operations.  */
227     integerPart addSignificand(const APFloat &);
228     integerPart subtractSignificand(const APFloat &, integerPart);
229     lostFraction addOrSubtractSignificand(const APFloat &, bool subtract);
230     lostFraction multiplySignificand(const APFloat &, const APFloat *);
231     lostFraction divideSignificand(const APFloat &);
232     void incrementSignificand();
233     void initialize(const fltSemantics *);
234     void shiftSignificandLeft(unsigned int);
235     lostFraction shiftSignificandRight(unsigned int);
236     unsigned int significandLSB() const;
237     unsigned int significandMSB() const;
238     void zeroSignificand();
239
240     /* Arithmetic on special values.  */
241     opStatus addOrSubtractSpecials(const APFloat &, bool subtract);
242     opStatus divideSpecials(const APFloat &);
243     opStatus multiplySpecials(const APFloat &);
244
245     /* Miscellany.  */
246     opStatus normalize(roundingMode, lostFraction);
247     opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
248     cmpResult compareAbsoluteValue(const APFloat &) const;
249     opStatus handleOverflow(roundingMode);
250     bool roundAwayFromZero(roundingMode, lostFraction);
251     opStatus convertFromUnsignedInteger(integerPart *, unsigned int,
252                                         roundingMode);
253     lostFraction combineLostFractions(lostFraction, lostFraction);
254     opStatus convertFromHexadecimalString(const char *, roundingMode);
255
256     void assign(const APFloat &);
257     void copySignificand(const APFloat &);
258     void freeSignificand();
259
260     /* What kind of semantics does this value obey?  */
261     const fltSemantics *semantics;
262
263     /* Significand - the fraction with an explicit integer bit.  Must be
264        at least one bit wider than the target precision.  */
265     union Significand
266     {
267       integerPart part;
268       integerPart *parts;
269     } significand;
270
271     /* The exponent - a signed number.  */
272     exponent_t exponent;
273
274     /* What kind of floating point number this is.  */
275     fltCategory category: 2;
276
277     /* The sign bit of this number.  */
278     unsigned int sign: 1;
279   };
280 } /* namespace llvm */
281
282 #endif /* LLVM_FLOAT_H */