llvm.org GIT mirror llvm / a15d890
Modify APFloat to take a StringRef instead of a c string. This also adds unit tests to APFloat that mainly tests the string handling of APFloat, but not much else of it's api. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79210 91177308-0d34-0410-b5e6-96231b3b80d8 Erick Tryzelaar 11 years ago
3 changed file(s) with 229 addition(s) and 79 deletion(s). Raw diff Collapse all Expand all
108108 typedef signed short exponent_t;
109109
110110 struct fltSemantics;
111 struct StringRef;
111112
112113 /* When bits of a floating point number are truncated, this enum is
113114 used to indicate what fraction of the LSB those bits represented.
171172 };
172173
173174 // Constructors.
174 APFloat(const fltSemantics &, const char *);
175 APFloat(const fltSemantics &, const StringRef &);
175176 APFloat(const fltSemantics &, integerPart);
176177 APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0);
177178 explicit APFloat(double d);
233234 bool, roundingMode);
234235 opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
235236 bool, roundingMode);
236 opStatus convertFromString(const char *, roundingMode);
237 opStatus convertFromString(const StringRef&, roundingMode);
237238 APInt bitcastToAPInt() const;
238239 double convertToDouble() const;
239240 float convertToFloat() const;
311312 roundingMode, bool *) const;
312313 opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
313314 roundingMode);
314 opStatus convertFromHexadecimalString(const char *, roundingMode);
315 opStatus convertFromDecimalString (const char *, roundingMode);
315 opStatus convertFromHexadecimalString(const StringRef&, roundingMode);
316 opStatus convertFromDecimalString (const StringRef&, roundingMode);
316317 char *convertNormalToHexString(char *, unsigned int, bool,
317318 roundingMode) const;
318319 opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "llvm/ADT/APFloat.h"
15 #include "llvm/ADT/StringRef.h"
1516 #include "llvm/ADT/FoldingSet.h"
1617 #include "llvm/Support/ErrorHandling.h"
1718 #include "llvm/Support/MathExtras.h"
122123 If the exponent overflows, returns a large exponent with the
123124 appropriate sign. */
124125 static int
125 readExponent(const char *p)
126 readExponent(StringRef::iterator begin, StringRef::iterator end)
126127 {
127128 bool isNegative;
128129 unsigned int absExponent;
129130 const unsigned int overlargeExponent = 24000; /* FIXME. */
131 StringRef::iterator p = begin;
132
133 assert(p != end && "Exponent has no digits");
130134
131135 isNegative = (*p == '-');
132 if (*p == '-' || *p == '+')
136 if (*p == '-' || *p == '+') {
133137 p++;
138 assert(p != end && "Exponent has no digits");
139 }
134140
135141 absExponent = decDigitValue(*p++);
136 assert (absExponent < 10U);
137
138 for (;;) {
142 assert(absExponent < 10U && "Invalid character in exponent");
143
144 for (; p != end; ++p) {
139145 unsigned int value;
140146
141147 value = decDigitValue(*p);
142 if (value >= 10U)
143 break;
144
145 p++;
148 assert(value < 10U && "Invalid character in exponent");
149
146150 value += absExponent * 10;
147151 if (absExponent >= overlargeExponent) {
148152 absExponent = overlargeExponent;
151155 absExponent = value;
152156 }
153157
158 assert(p == end && "Invalid exponent in exponent");
159
154160 if (isNegative)
155161 return -(int) absExponent;
156162 else
160166 /* This is ugly and needs cleaning up, but I don't immediately see
161167 how whilst remaining safe. */
162168 static int
163 totalExponent(const char *p, int exponentAdjustment)
169 totalExponent(StringRef::iterator p, StringRef::iterator end,
170 int exponentAdjustment)
164171 {
165172 int unsignedExponent;
166173 bool negative, overflow;
174181
175182 unsignedExponent = 0;
176183 overflow = false;
177 for(;;) {
184 for(; p != end; ++p) {
178185 unsigned int value;
179186
180187 value = decDigitValue(*p);
181 if(value >= 10U)
182 break;
183
184 p++;
188 assert(value < 10U && "Invalid character in exponent");
189
185190 unsignedExponent = unsignedExponent * 10 + value;
186191 if(unsignedExponent > 65535)
187192 overflow = true;
205210 return exponent;
206211 }
207212
208 static const char *
209 skipLeadingZeroesAndAnyDot(const char *p, const char **dot)
210 {
211 *dot = 0;
212 while(*p == '0')
213 static StringRef::iterator
214 skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
215 StringRef::iterator *dot)
216 {
217 StringRef::iterator p = begin;
218 *dot = end;
219 while(*p == '0' && p != end)
213220 p++;
214221
215222 if(*p == '.') {
216223 *dot = p++;
217 while(*p == '0')
224
225 assert(end - begin != 1 && "String cannot be just a dot");
226
227 while(*p == '0' && p != end)
218228 p++;
219229 }
220230
242252 };
243253
244254 static void
245 interpretDecimal(const char *p, decimalInfo *D)
246 {
247 const char *dot;
248
249 p = skipLeadingZeroesAndAnyDot (p, &dot);
255 interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
256 decimalInfo *D)
257 {
258 StringRef::iterator dot = end;
259 StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot);
250260
251261 D->firstSigDigit = p;
252262 D->exponent = 0;
253263 D->normalizedExponent = 0;
254264
255 for (;;) {
265 for (; p != end; ++p) {
256266 if (*p == '.') {
257 assert(dot == 0);
267 assert(dot == end && "Multiple dots in float");
258268 dot = p++;
269 if (p == end)
270 break;
259271 }
260272 if (decDigitValue(*p) >= 10U)
261273 break;
262 p++;
263 }
264
265 /* If number is all zerooes accept any exponent. */
274 }
275
276 if (p != end) {
277 assert((*p == 'e' || *p == 'E') && "Invalid character in digit string");
278
279 /* p points to the first non-digit in the string */
280 if (*p == 'e' || *p == 'E') {
281 D->exponent = readExponent(p + 1, end);
282 }
283
284 /* Implied decimal point? */
285 if (dot == end)
286 dot = p;
287 }
288
289 /* If number is all zeroes accept any exponent. */
266290 if (p != D->firstSigDigit) {
267 if (*p == 'e' || *p == 'E')
268 D->exponent = readExponent(p + 1);
269
270 /* Implied decimal point? */
271 if (!dot)
272 dot = p;
273
274291 /* Drop insignificant trailing zeroes. */
275 do
292 if (p != begin) {
276293 do
277 p--;
278 while (*p == '0');
279 while (*p == '.');
294 do
295 p--;
296 while (p != begin && *p == '0');
297 while (p != begin && *p == '.');
298 }
280299
281300 /* Adjust the exponents for any decimal point. */
282301 D->exponent += static_cast((dot - p) - (dot > p));
292311 DIGITVALUE is the first hex digit of the fraction, P points to
293312 the next digit. */
294313 static lostFraction
295 trailingHexadecimalFraction(const char *p, unsigned int digitValue)
314 trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
315 unsigned int digitValue)
296316 {
297317 unsigned int hexDigit;
298318
306326 /* Otherwise we need to find the first non-zero digit. */
307327 while(*p == '0')
308328 p++;
329
330 assert(p != end && "Invalid trailing hexadecimal fraction!");
309331
310332 hexDigit = hexDigitValue(*p);
311333
680702 makeNaN(type);
681703 }
682704
683 APFloat::APFloat(const fltSemantics &ourSemantics, const char *text)
705 APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)
684706 {
685707 assertArithmeticOK(ourSemantics);
686708 initialize(&ourSemantics);
21062128 }
21072129
21082130 APFloat::opStatus
2109 APFloat::convertFromHexadecimalString(const char *p,
2131 APFloat::convertFromHexadecimalString(const StringRef &s,
21102132 roundingMode rounding_mode)
21112133 {
21122134 lostFraction lost_fraction;
21132135 integerPart *significand;
21142136 unsigned int bitPos, partsCount;
2115 const char *dot, *firstSignificantDigit;
2137 StringRef::iterator dot, firstSignificantDigit;
21162138
21172139 zeroSignificand();
21182140 exponent = 0;
21232145 bitPos = partsCount * integerPartWidth;
21242146
21252147 /* Skip leading zeroes and any (hexa)decimal point. */
2126 p = skipLeadingZeroesAndAnyDot(p, &dot);
2148 StringRef::iterator p = skipLeadingZeroesAndAnyDot(s.begin(), s.end(), &dot);
21272149 firstSignificantDigit = p;
21282150
2129 for(;;) {
2151 for(; p != s.end();) {
21302152 integerPart hex_value;
21312153
21322154 if(*p == '.') {
21422164
21432165 p++;
21442166
2145 /* Store the number whilst 4-bit nibbles remain. */
2146 if(bitPos) {
2147 bitPos -= 4;
2148 hex_value <<= bitPos % integerPartWidth;
2149 significand[bitPos / integerPartWidth] |= hex_value;
2167 if (p == s.end()) {
2168 break;
21502169 } else {
2151 lost_fraction = trailingHexadecimalFraction(p, hex_value);
2152 while(hexDigitValue(*p) != -1U)
2153 p++;
2154 break;
2170 /* Store the number whilst 4-bit nibbles remain. */
2171 if(bitPos) {
2172 bitPos -= 4;
2173 hex_value <<= bitPos % integerPartWidth;
2174 significand[bitPos / integerPartWidth] |= hex_value;
2175 } else {
2176 lost_fraction = trailingHexadecimalFraction(p, s.end(), hex_value);
2177 while(p != s.end() && hexDigitValue(*p) != -1U)
2178 p++;
2179 break;
2180 }
21552181 }
21562182 }
21572183
21582184 /* Hex floats require an exponent but not a hexadecimal point. */
2159 assert(*p == 'p' || *p == 'P');
2185 assert(p != s.end() && (*p == 'p' || *p == 'P') &&
2186 "Hex strings require an exponent");
21602187
21612188 /* Ignore the exponent if we are zero. */
21622189 if(p != firstSignificantDigit) {
21792206 expAdjustment -= partsCount * integerPartWidth;
21802207
21812208 /* Adjust for the given exponent. */
2182 exponent = totalExponent(p, expAdjustment);
2209 exponent = totalExponent(p, s.end(), expAdjustment);
21832210 }
21842211
21852212 return normalize(rounding_mode, lost_fraction);
22712298 }
22722299
22732300 APFloat::opStatus
2274 APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
2301 APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mode)
22752302 {
22762303 decimalInfo D;
22772304 opStatus fs;
22782305
22792306 /* Scan the text. */
2280 interpretDecimal(p, &D);
2307 StringRef::iterator p = str.begin();
2308 interpretDecimal(p, str.end(), &D);
22812309
22822310 /* Handle the quick cases. First the case of no significant digits,
22832311 i.e. zero, and then exponents that are obviously too large or too
23322360 multiplier = 1;
23332361
23342362 do {
2335 if (*p == '.')
2363 if (*p == '.') {
23362364 p++;
2337
2365 if (p == str.end()) {
2366 break;
2367 }
2368 }
23382369 decValue = decDigitValue(*p++);
2370 assert(decValue < 10U && "Invalid character in digit string");
23392371 multiplier *= 10;
23402372 val = val * 10 + decValue;
23412373 /* The maximum number that can be multiplied by ten with any
23632395 }
23642396
23652397 APFloat::opStatus
2366 APFloat::convertFromString(const char *p, roundingMode rounding_mode)
2398 APFloat::convertFromString(const StringRef &str, roundingMode rounding_mode)
23672399 {
23682400 assertArithmeticOK(*semantics);
2401 assert(!str.empty() && "Invalid string length");
23692402
23702403 /* Handle a leading minus sign. */
2371 if(*p == '-')
2372 sign = 1, p++;
2373 else
2404 StringRef::iterator p = str.begin();
2405 size_t slen = str.size();
2406 unsigned isNegative = str.front() == '-';
2407 if(isNegative) {
2408 sign = 1;
2409 p++;
2410 slen--;
2411 assert(slen && "String is only a minus!");
2412 } else {
23742413 sign = 0;
2375
2376 if(p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
2377 return convertFromHexadecimalString(p + 2, rounding_mode);
2378
2379 return convertFromDecimalString(p, rounding_mode);
2414 }
2415
2416 if(slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
2417 assert(slen - 2 && "Invalid string");
2418 return convertFromHexadecimalString(str.substr(isNegative + 2),
2419 rounding_mode);
2420 }
2421
2422 return convertFromDecimalString(str.substr(isNegative), rounding_mode);
23802423 }
23812424
23822425 /* Write out a hexadecimal representation of the floating point value
27432786 float
27442787 APFloat::convertToFloat() const
27452788 {
2746 assert(semantics == (const llvm::fltSemantics*)&IEEEsingle);
2789 assert(semantics == (const llvm::fltSemantics*)&IEEEsingle && "Float semantics are not IEEEsingle");
27472790 APInt api = bitcastToAPInt();
27482791 return api.bitsToFloat();
27492792 }
27512794 double
27522795 APFloat::convertToDouble() const
27532796 {
2754 assert(semantics == (const llvm::fltSemantics*)&IEEEdouble);
2797 assert(semantics == (const llvm::fltSemantics*)&IEEEdouble && "Float semantics are not IEEEdouble");
27552798 APInt api = bitcastToAPInt();
27562799 return api.bitsToDouble();
27572800 }
0 //===- llvm/unittest/ADT/APFloat.cpp - APFloat unit tests ---------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include
10 #include "llvm/Support/raw_ostream.h"
11 #include "gtest/gtest.h"
12 #include "llvm/ADT/APFloat.h"
13 #include "llvm/ADT/SmallString.h"
14
15 using namespace llvm;
16
17 namespace {
18
19 TEST(APFloatTest, Zero) {
20 ASSERT_EQ(0.0f, APFloat(APFloat::IEEEsingle, 0.0f).convertToFloat());
21 ASSERT_EQ(-0.0f, APFloat(APFloat::IEEEsingle, -0.0f).convertToFloat());
22
23 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, 0.0).convertToDouble());
24 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, -0.0).convertToDouble());
25 }
26
27 TEST(APFloatTest, SemanticsDeath) {
28 ASSERT_DEATH(APFloat(APFloat::IEEEsingle, 0.0f).convertToDouble(), "Float semantics are not IEEEdouble");
29 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, 0.0 ).convertToFloat(), "Float semantics are not IEEEsingle");
30 }
31
32 TEST(APFloatTest, fromString) {
33 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0").convertToDouble());
34 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.").convertToDouble());
35 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, ".0").convertToDouble());
36 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.0").convertToDouble());
37 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0").convertToDouble());
38 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.").convertToDouble());
39 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0").convertToDouble());
40 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.0").convertToDouble());
41 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0e1234").convertToDouble());
42 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0e1234").convertToDouble());
43 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "00000.").convertToDouble());
44 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0000.00000").convertToDouble());
45 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, ".00000").convertToDouble());
46 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.").convertToDouble());
47 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.e1").convertToDouble());
48 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.e+1").convertToDouble());
49 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0.e-1").convertToDouble());
50 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e0").convertToDouble());
51 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e-0").convertToDouble());
52 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e1234").convertToDouble());
53 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e-1234").convertToDouble());
54
55 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0p1").convertToDouble());
56 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p1").convertToDouble());
57 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x00000.p1").convertToDouble());
58 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0000.00000p1").convertToDouble());
59 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x.00000p1").convertToDouble());
60 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0.p1").convertToDouble());
61 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0p1234").convertToDouble());
62 ASSERT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p1234").convertToDouble());
63 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x00000.p1234").convertToDouble());
64 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0000.00000p1234").convertToDouble());
65 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x.00000p1234").convertToDouble());
66 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, "0x0.p1234").convertToDouble());
67
68 ASSERT_EQ(0.0, APFloat(APFloat::IEEEdouble, StringRef("0e1\02", 3)).convertToDouble());
69 }
70
71 TEST(APFloatTest, StringDeath) {
72 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, ""), "Invalid string length");
73 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "-"), "String is only a minus!");
74 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0x"), "Invalid string");
75 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "."), "String cannot be just a dot");
76 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "-."), "String cannot be just a dot");
77 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0x."), "String cannot be just a dot");
78 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "-0x."),"String cannot be just a dot");
79 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0x0"), "Hex strings require an exponent");
80 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0e"), "Exponent has no digits");
81 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0e+"), "Exponent has no digits");
82 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0e-"), "Exponent has no digits");
83
84 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("\0", 1)), "Invalid character in digit string");
85 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\0", 2)), "Invalid character in digit string");
86 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\02", 3)), "Invalid character in digit string");
87 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\02e1", 5)), "Invalid character in digit string");
88 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e\0", 3)), "Invalid character in exponent");
89 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e1\0", 4)), "Invalid character in exponent");
90 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e1\02", 5)), "Invalid character in exponent");
91
92 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "1.0f"), "Invalid character in digit string");
93
94 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x\0", 3)), "Hex strings require an exponent");
95 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\0", 4)), "Hex strings require an exponent");
96 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\02", 5)), "Hex strings require an exponent");
97 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\02p1", 7)), "Hex strings require an exponent");
98 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p\0", 5)), "Invalid character in exponent");
99 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p1\0", 6)), "Invalid character in exponent");
100 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p1\02", 7)), "Invalid character in exponent");
101
102 ASSERT_DEATH(APFloat(APFloat::IEEEdouble, "0x1p0f"), "Invalid character in exponent");
103 }
104
105 }