]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/digitlst.cpp
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / i18n / digitlst.cpp
CommitLineData
b75a7d8f
A
1/*
2**********************************************************************
57a6839d 3* Copyright (C) 1997-2014, International Business Machines
b75a7d8f
A
4* Corporation and others. All Rights Reserved.
5**********************************************************************
6*
7* File DIGITLST.CPP
8*
9* Modification History:
10*
11* Date Name Description
12* 03/21/97 clhuang Converted from java.
13* 03/21/97 clhuang Implemented with new APIs.
14* 03/27/97 helena Updated to pass the simple test after code review.
15* 03/31/97 aliu Moved isLONG_MIN to here, and fixed it.
16* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char.
17* Reworked representation by replacing fDecimalAt
18* with fExponent.
19* 04/16/97 aliu Rewrote set() and getDouble() to use sprintf/atof
20* to do digit conversion.
21* 09/09/97 aliu Modified for exponential notation support.
22* 08/02/98 stephen Added nearest/even rounding
23* Fixed bug in fitsIntoLong
24******************************************************************************
25*/
26
b75a7d8f 27#include "digitlst.h"
46f4442e
A
28
29#if !UCONFIG_NO_FORMATTING
30#include "unicode/putil.h"
729e4ab9
A
31#include "charstr.h"
32#include "cmemory.h"
374ca955 33#include "cstring.h"
4388f060 34#include "mutex.h"
374ca955 35#include "putilimp.h"
46f4442e 36#include "uassert.h"
b75a7d8f
A
37#include <stdlib.h>
38#include <limits.h>
39#include <string.h>
40#include <stdio.h>
729e4ab9
A
41#include <limits>
42
b75a7d8f
A
43// ***************************************************************************
44// class DigitList
729e4ab9
A
45// A wrapper onto decNumber.
46// Used to be standalone.
b75a7d8f
A
47// ***************************************************************************
48
49/**
729e4ab9
A
50 * This is the zero digit. The base for the digits returned by getDigit()
51 * Note that it is the platform invariant digit, and is not Unicode.
b75a7d8f
A
52 */
53#define kZero '0'
54
b75a7d8f
A
55
56/* Only for 32 bit numbers. Ignore the negative sign. */
51004dcb
A
57//static const char LONG_MIN_REP[] = "2147483648";
58//static const char I64_MIN_REP[] = "9223372036854775808";
374ca955 59
b75a7d8f
A
60
61U_NAMESPACE_BEGIN
62
b75a7d8f
A
63// -------------------------------------
64// default constructor
65
66DigitList::DigitList()
67{
729e4ab9
A
68 uprv_decContextDefault(&fContext, DEC_INIT_BASE);
69 fContext.traps = 0;
70 uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
71 fContext.digits = fStorage.getCapacity();
72
73 fDecNumber = fStorage.getAlias();
74 uprv_decNumberZero(fDecNumber);
75
51004dcb 76 internalSetDouble(0.0);
b75a7d8f
A
77}
78
79// -------------------------------------
80
81DigitList::~DigitList()
82{
83}
84
85// -------------------------------------
86// copy constructor
87
88DigitList::DigitList(const DigitList &other)
89{
729e4ab9 90 fDecNumber = fStorage.getAlias();
b75a7d8f
A
91 *this = other;
92}
93
729e4ab9 94
b75a7d8f
A
95// -------------------------------------
96// assignment operator
97
98DigitList&
99DigitList::operator=(const DigitList& other)
100{
101 if (this != &other)
102 {
729e4ab9
A
103 uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
104
105 if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
106 fDecNumber = fStorage.resize(other.fStorage.getCapacity());
107 }
108 // Always reset the fContext.digits, even if fDecNumber was not reallocated,
109 // because above we copied fContext from other.fContext.
110 fContext.digits = fStorage.getCapacity();
111 uprv_decNumberCopy(fDecNumber, other.fDecNumber);
112
4388f060
A
113 {
114 // fDouble is lazily created and cached.
115 // Avoid potential races with that happening with other.fDouble
116 // while we are doing the assignment.
117 Mutex mutex;
51004dcb
A
118
119 if(other.fHave==kDouble) {
120 fUnion.fDouble = other.fUnion.fDouble;
121 } else if(other.fHave==kInt64) {
122 fUnion.fInt64 = other.fUnion.fInt64;
123 }
124 fHave = other.fHave;
4388f060 125 }
b75a7d8f
A
126 }
127 return *this;
128}
129
130// -------------------------------------
729e4ab9 131// operator == (does not exactly match the old DigitList function)
b75a7d8f
A
132
133UBool
134DigitList::operator==(const DigitList& that) const
135{
729e4ab9
A
136 if (this == &that) {
137 return TRUE;
138 }
139 decNumber n; // Has space for only a none digit value.
140 decContext c;
141 uprv_decContextDefault(&c, DEC_INIT_BASE);
142 c.digits = 1;
143 c.traps = 0;
144
145 uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
146 UBool result = decNumberIsZero(&n);
147 return result;
b75a7d8f
A
148}
149
150// -------------------------------------
729e4ab9
A
151// comparison function. Returns
152// Not Comparable : -2
153// < : -1
154// == : 0
155// > : +1
156int32_t DigitList::compare(const DigitList &other) {
157 decNumber result;
158 int32_t savedDigits = fContext.digits;
159 fContext.digits = 1;
160 uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
161 fContext.digits = savedDigits;
162 if (decNumberIsZero(&result)) {
163 return 0;
164 } else if (decNumberIsSpecial(&result)) {
165 return -2;
166 } else if (result.bits & DECNEG) {
167 return -1;
168 } else {
169 return 1;
170 }
171}
b75a7d8f 172
b75a7d8f 173
729e4ab9
A
174// -------------------------------------
175// Reduce - remove trailing zero digits.
176void
177DigitList::reduce() {
178 uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
b75a7d8f
A
179}
180
181
729e4ab9
A
182// -------------------------------------
183// trim - remove trailing fraction zero digits.
184void
185DigitList::trim() {
186 uprv_decNumberTrim(fDecNumber);
187}
b75a7d8f
A
188
189// -------------------------------------
729e4ab9
A
190// Resets the digit list; sets all the digits to zero.
191
192void
193DigitList::clear()
194{
195 uprv_decNumberZero(fDecNumber);
196 uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
51004dcb 197 internalSetDouble(0.0);
729e4ab9
A
198}
199
b75a7d8f
A
200
201/**
729e4ab9 202 * Formats a int64_t number into a base 10 string representation, and NULL terminates it.
b75a7d8f 203 * @param number The number to format
729e4ab9
A
204 * @param outputStr The string to output to. Must be at least MAX_DIGITS+2 in length (21),
205 * to hold the longest int64_t value.
b75a7d8f
A
206 * @return the number of digits written, not including the sign.
207 */
208static int32_t
729e4ab9
A
209formatBase10(int64_t number, char *outputStr) {
210 // The number is output backwards, starting with the LSD.
211 // Fill the buffer from the far end. After the number is complete,
212 // slide the string contents to the front.
213
214 const int32_t MAX_IDX = MAX_DIGITS+2;
215 int32_t destIdx = MAX_IDX;
216 outputStr[--destIdx] = 0;
b75a7d8f 217
729e4ab9
A
218 int64_t n = number;
219 if (number < 0) { // Negative numbers are slightly larger than a postive
220 outputStr[--destIdx] = (char)(-(n % 10) + kZero);
221 n /= -10;
b75a7d8f 222 }
729e4ab9
A
223 do {
224 outputStr[--destIdx] = (char)(n % 10 + kZero);
225 n /= 10;
226 } while (n > 0);
227
228 if (number < 0) {
229 outputStr[--destIdx] = '-';
b75a7d8f
A
230 }
231
729e4ab9
A
232 // Slide the number to the start of the output str
233 U_ASSERT(destIdx >= 0);
234 int32_t length = MAX_IDX - destIdx;
235 uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
b75a7d8f 236
729e4ab9
A
237 return length;
238}
239
240
241// -------------------------------------
4388f060
A
242//
243// setRoundingMode()
244// For most modes, the meaning and names are the same between the decNumber library
245// (which DigitList follows) and the ICU Formatting Rounding Mode values.
246// The flag constants are different, however.
247//
248// Note that ICU's kRoundingUnnecessary is not implemented directly by DigitList.
249// This mode, inherited from Java, means that numbers that would not format exactly
250// will return an error when formatting is attempted.
729e4ab9
A
251
252void
253DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
254 enum rounding r;
255
256 switch (m) {
257 case DecimalFormat::kRoundCeiling: r = DEC_ROUND_CEILING; break;
258 case DecimalFormat::kRoundFloor: r = DEC_ROUND_FLOOR; break;
259 case DecimalFormat::kRoundDown: r = DEC_ROUND_DOWN; break;
260 case DecimalFormat::kRoundUp: r = DEC_ROUND_UP; break;
261 case DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
262 case DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
263 case DecimalFormat::kRoundHalfUp: r = DEC_ROUND_HALF_UP; break;
4388f060 264 case DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break;
729e4ab9
A
265 default:
266 // TODO: how to report the problem?
267 // Leave existing mode unchanged.
268 r = uprv_decContextGetRounding(&fContext);
b75a7d8f 269 }
729e4ab9
A
270 uprv_decContextSetRounding(&fContext, r);
271
272}
273
274
275// -------------------------------------
276
277void
278DigitList::setPositive(UBool s) {
279 if (s) {
280 fDecNumber->bits &= ~DECNEG;
281 } else {
282 fDecNumber->bits |= DECNEG;
b75a7d8f 283 }
51004dcb 284 internalClear();
729e4ab9
A
285}
286// -------------------------------------
287
288void
289DigitList::setDecimalAt(int32_t d) {
290 U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN
291 U_ASSERT(d-1>-999999999);
292 U_ASSERT(d-1< 999999999);
293 int32_t adjustedDigits = fDecNumber->digits;
294 if (decNumberIsZero(fDecNumber)) {
295 // Account for difference in how zero is represented between DigitList & decNumber.
296 adjustedDigits = 0;
b75a7d8f 297 }
729e4ab9 298 fDecNumber->exponent = d - adjustedDigits;
51004dcb 299 internalClear();
729e4ab9 300}
b75a7d8f 301
729e4ab9
A
302int32_t
303DigitList::getDecimalAt() {
304 U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN
305 if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
306 return fDecNumber->exponent; // Exponent should be zero for these cases.
307 }
308 return fDecNumber->exponent + fDecNumber->digits;
309}
b75a7d8f 310
729e4ab9
A
311void
312DigitList::setCount(int32_t c) {
313 U_ASSERT(c <= fContext.digits);
314 if (c == 0) {
315 // For a value of zero, DigitList sets all fields to zero, while
316 // decNumber keeps one digit (with that digit being a zero)
317 c = 1;
318 fDecNumber->lsu[0] = 0;
b75a7d8f 319 }
729e4ab9 320 fDecNumber->digits = c;
51004dcb 321 internalClear();
b75a7d8f
A
322}
323
729e4ab9
A
324int32_t
325DigitList::getCount() const {
326 if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) {
327 // The extra test for exponent==0 is needed because parsing sometimes appends
328 // zero digits. It's bogus, decimalFormatter parsing needs to be cleaned up.
329 return 0;
330 } else {
331 return fDecNumber->digits;
332 }
333}
334
335void
336DigitList::setDigit(int32_t i, char v) {
337 int32_t count = fDecNumber->digits;
338 U_ASSERT(i<count);
339 U_ASSERT(v>='0' && v<='9');
340 v &= 0x0f;
341 fDecNumber->lsu[count-i-1] = v;
51004dcb 342 internalClear();
729e4ab9
A
343}
344
345char
346DigitList::getDigit(int32_t i) {
347 int32_t count = fDecNumber->digits;
348 U_ASSERT(i<count);
349 return fDecNumber->lsu[count-i-1] + '0';
350}
351
352// copied from DigitList::getDigit()
353uint8_t
354DigitList::getDigitValue(int32_t i) {
355 int32_t count = fDecNumber->digits;
356 U_ASSERT(i<count);
357 return fDecNumber->lsu[count-i-1];
358}
359
360// -------------------------------------
361// Appends the digit to the digit list if it's not out of scope.
362// Ignores the digit, otherwise.
363//
364// This function is horribly inefficient to implement with decNumber because
365// the digits are stored least significant first, which requires moving all
366// existing digits down one to make space for the new one to be appended.
367//
368void
369DigitList::append(char digit)
370{
371 U_ASSERT(digit>='0' && digit<='9');
372 // Ignore digits which exceed the precision we can represent
373 // And don't fix for larger precision. Fix callers instead.
374 if (decNumberIsZero(fDecNumber)) {
375 // Zero needs to be special cased because of the difference in the way
376 // that the old DigitList and decNumber represent it.
377 // digit cout was zero for digitList, is one for decNumber
378 fDecNumber->lsu[0] = digit & 0x0f;
379 fDecNumber->digits = 1;
380 fDecNumber->exponent--; // To match the old digit list implementation.
381 } else {
382 int32_t nDigits = fDecNumber->digits;
383 if (nDigits < fContext.digits) {
384 int i;
385 for (i=nDigits; i>0; i--) {
386 fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
387 }
388 fDecNumber->lsu[0] = digit & 0x0f;
389 fDecNumber->digits++;
390 // DigitList emulation - appending doesn't change the magnitude of existing
391 // digits. With decNumber's decimal being after the
392 // least signficant digit, we need to adjust the exponent.
393 fDecNumber->exponent--;
394 }
395 }
51004dcb 396 internalClear();
729e4ab9
A
397}
398
399// -------------------------------------
400
b75a7d8f 401/**
4388f060 402 * Currently, getDouble() depends on strtod() to do its conversion.
b75a7d8f
A
403 *
404 * WARNING!!
405 * This is an extremely costly function. ~1/2 of the conversion time
406 * can be linked to this function.
407 */
408double
729e4ab9 409DigitList::getDouble() const
b75a7d8f 410{
4388f060
A
411 static char gDecimal = 0;
412 char decimalSeparator;
413 {
414 Mutex mutex;
51004dcb
A
415 if (fHave == kDouble) {
416 return fUnion.fDouble;
417 } else if(fHave == kInt64) {
418 return (double)fUnion.fInt64;
4388f060
A
419 }
420 decimalSeparator = gDecimal;
729e4ab9 421 }
729e4ab9 422
4388f060
A
423 if (decimalSeparator == 0) {
424 // We need to know the decimal separator character that will be used with strtod().
425 // Depends on the C runtime global locale.
426 // Most commonly is '.'
427 // TODO: caching could fail if the global locale is changed on the fly.
729e4ab9 428 char rep[MAX_DIGITS];
729e4ab9 429 sprintf(rep, "%+1.1f", 1.0);
4388f060 430 decimalSeparator = rep[2];
b75a7d8f
A
431 }
432
4388f060 433 double tDouble = 0.0;
729e4ab9 434 if (isZero()) {
4388f060 435 tDouble = 0.0;
729e4ab9 436 if (decNumberIsNegative(fDecNumber)) {
4388f060 437 tDouble /= -1;
729e4ab9
A
438 }
439 } else if (isInfinite()) {
440 if (std::numeric_limits<double>::has_infinity) {
4388f060 441 tDouble = std::numeric_limits<double>::infinity();
729e4ab9 442 } else {
4388f060 443 tDouble = std::numeric_limits<double>::max();
729e4ab9
A
444 }
445 if (!isPositive()) {
51004dcb 446 tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
729e4ab9
A
447 }
448 } else {
449 MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
450 // Note: 14 is a magic constant from the decNumber library documentation,
451 // the max number of extra characters beyond the number of digits
452 // needed to represent the number in string form. Add a few more
453 // for the additional digits we retain.
454
455 // Round down to appx. double precision, if the number is longer than that.
456 // Copy the number first, so that we don't modify the original.
457 if (getCount() > MAX_DBL_DIGITS + 3) {
458 DigitList numToConvert(*this);
459 numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good.
460 numToConvert.round(MAX_DBL_DIGITS+3);
51004dcb 461 uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
729e4ab9
A
462 // TODO: how many extra digits should be included for an accurate conversion?
463 } else {
51004dcb 464 uprv_decNumberToString(this->fDecNumber, s.getAlias());
729e4ab9
A
465 }
466 U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
467
4388f060 468 if (decimalSeparator != '.') {
51004dcb 469 char *decimalPt = strchr(s.getAlias(), '.');
729e4ab9 470 if (decimalPt != NULL) {
4388f060 471 *decimalPt = decimalSeparator;
729e4ab9
A
472 }
473 }
474 char *end = NULL;
51004dcb 475 tDouble = uprv_strtod(s.getAlias(), &end);
4388f060
A
476 }
477 {
478 Mutex mutex;
479 DigitList *nonConstThis = const_cast<DigitList *>(this);
51004dcb 480 nonConstThis->internalSetDouble(tDouble);
4388f060 481 gDecimal = decimalSeparator;
729e4ab9 482 }
4388f060 483 return tDouble;
b75a7d8f
A
484}
485
486// -------------------------------------
487
488/**
729e4ab9
A
489 * convert this number to an int32_t. Round if there is a fractional part.
490 * Return zero if the number cannot be represented.
b75a7d8f 491 */
374ca955 492int32_t DigitList::getLong() /*const*/
b75a7d8f 493{
729e4ab9
A
494 int32_t result = 0;
495 if (fDecNumber->digits + fDecNumber->exponent > 10) {
496 // Overflow, absolute value too big.
497 return result;
b75a7d8f 498 }
729e4ab9
A
499 if (fDecNumber->exponent != 0) {
500 // Force to an integer, with zero exponent, rounding if necessary.
501 // (decNumberToInt32 will only work if the exponent is exactly zero.)
502 DigitList copy(*this);
503 DigitList zero;
504 uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
505 result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
506 } else {
507 result = uprv_decNumberToInt32(fDecNumber, &fContext);
b75a7d8f 508 }
729e4ab9 509 return result;
b75a7d8f
A
510}
511
374ca955
A
512
513/**
729e4ab9
A
514 * convert this number to an int64_t. Truncate if there is a fractional part.
515 * Return zero if the number cannot be represented.
374ca955 516 */
729e4ab9 517int64_t DigitList::getInt64() /*const*/ {
51004dcb
A
518 if(fHave==kInt64) {
519 return fUnion.fInt64;
520 }
729e4ab9
A
521 // Truncate if non-integer.
522 // Return 0 if out of range.
523 // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digits)
524 //
525 if (fDecNumber->digits + fDecNumber->exponent > 19) {
526 // Overflow, absolute value too big.
527 return 0;
528 }
374ca955 529
729e4ab9
A
530 // The number of integer digits may differ from the number of digits stored
531 // in the decimal number.
532 // for 12.345 numIntDigits = 2, number->digits = 5
533 // for 12E4 numIntDigits = 6, number->digits = 2
534 // The conversion ignores the fraction digits in the first case,
535 // and fakes up extra zero digits in the second.
536 // TODO: It would be faster to store a table of powers of ten to multiply by
537 // instead of looping over zero digits, multiplying each time.
538
539 int32_t numIntDigits = fDecNumber->digits + fDecNumber->exponent;
540 uint64_t value = 0;
541 for (int32_t i = 0; i < numIntDigits; i++) {
542 // Loop is iterating over digits starting with the most significant.
543 // Numbers are stored with the least significant digit at index zero.
544 int32_t digitIndex = fDecNumber->digits - i - 1;
545 int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
546 value = value * (uint64_t)10 + (uint64_t)v;
547 }
374ca955 548
729e4ab9
A
549 if (decNumberIsNegative(fDecNumber)) {
550 value = ~value;
551 value += 1;
552 }
553 int64_t svalue = (int64_t)value;
554
555 // Check overflow. It's convenient that the MSD is 9 only on overflow, the amount of
556 // overflow can't wrap too far. The test will also fail -0, but
557 // that does no harm; the right answer is 0.
558 if (numIntDigits == 19) {
559 if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
560 (!decNumberIsNegative(fDecNumber) && svalue<0)) {
561 svalue = 0;
374ca955 562 }
374ca955 563 }
729e4ab9
A
564
565 return svalue;
566}
567
568
569/**
570 * Return a string form of this number.
571 * Format is as defined by the decNumber library, for interchange of
572 * decimal numbers.
573 */
574void DigitList::getDecimal(CharString &str, UErrorCode &status) {
575 if (U_FAILURE(status)) {
576 return;
577 }
374ca955 578
729e4ab9
A
579 // A decimal number in string form can, worst case, be 14 characters longer
580 // than the number of digits. So says the decNumber library doc.
581 int32_t maxLength = fDecNumber->digits + 14;
582 int32_t capacity = 0;
583 char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
584 if (U_FAILURE(status)) {
585 return; // Memory allocation error on growing the string.
374ca955 586 }
729e4ab9
A
587 U_ASSERT(capacity >= maxLength);
588 uprv_decNumberToString(this->fDecNumber, buffer);
589 U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
590 str.append(buffer, -1, status);
374ca955
A
591}
592
b75a7d8f 593/**
729e4ab9
A
594 * Return true if this is an integer value that can be held
595 * by an int32_t type.
b75a7d8f
A
596 */
597UBool
374ca955 598DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
b75a7d8f 599{
729e4ab9
A
600 if (decNumberIsSpecial(this->fDecNumber)) {
601 // NaN or Infinity. Does not fit in int32.
602 return FALSE;
b75a7d8f 603 }
729e4ab9
A
604 uprv_decNumberTrim(this->fDecNumber);
605 if (fDecNumber->exponent < 0) {
606 // Number contains fraction digits.
b75a7d8f 607 return FALSE;
729e4ab9
A
608 }
609 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
610 (fDecNumber->bits & DECNEG) != 0) {
611 // Negative Zero, not ingored. Cannot represent as a long.
612 return FALSE;
613 }
614 if (fDecNumber->digits + fDecNumber->exponent < 10) {
615 // The number is 9 or fewer digits.
616 // The max and min int32 are 10 digts, so this number fits.
617 // This is the common case.
b75a7d8f 618 return TRUE;
729e4ab9 619 }
b75a7d8f 620
729e4ab9
A
621 // TODO: Should cache these constants; construction is relatively costly.
622 // But not of huge consequence; they're only needed for 10 digit ints.
623 UErrorCode status = U_ZERO_ERROR;
624 DigitList min32; min32.set("-2147483648", status);
625 if (this->compare(min32) < 0) {
626 return FALSE;
627 }
628 DigitList max32; max32.set("2147483647", status);
629 if (this->compare(max32) > 0) {
630 return FALSE;
631 }
632 if (U_FAILURE(status)) {
633 return FALSE;
b75a7d8f 634 }
729e4ab9
A
635 return true;
636}
b75a7d8f 637
b75a7d8f 638
b75a7d8f 639
374ca955
A
640/**
641 * Return true if the number represented by this object can fit into
642 * a long.
643 */
644UBool
645DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
646{
729e4ab9
A
647 if (decNumberIsSpecial(this->fDecNumber)) {
648 // NaN or Infinity. Does not fit in int32.
649 return FALSE;
374ca955 650 }
729e4ab9
A
651 uprv_decNumberTrim(this->fDecNumber);
652 if (fDecNumber->exponent < 0) {
653 // Number contains fraction digits.
374ca955 654 return FALSE;
374ca955 655 }
729e4ab9
A
656 if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
657 (fDecNumber->bits & DECNEG) != 0) {
658 // Negative Zero, not ingored. Cannot represent as a long.
659 return FALSE;
660 }
661 if (fDecNumber->digits + fDecNumber->exponent < 19) {
662 // The number is 18 or fewer digits.
663 // The max and min int64 are 19 digts, so this number fits.
664 // This is the common case.
374ca955 665 return TRUE;
729e4ab9 666 }
374ca955 667
729e4ab9
A
668 // TODO: Should cache these constants; construction is relatively costly.
669 // But not of huge consequence; they're only needed for 19 digit ints.
670 UErrorCode status = U_ZERO_ERROR;
671 DigitList min64; min64.set("-9223372036854775808", status);
672 if (this->compare(min64) < 0) {
673 return FALSE;
674 }
675 DigitList max64; max64.set("9223372036854775807", status);
676 if (this->compare(max64) > 0) {
677 return FALSE;
678 }
679 if (U_FAILURE(status)) {
680 return FALSE;
681 }
682 return true;
374ca955
A
683}
684
685
b75a7d8f
A
686// -------------------------------------
687
374ca955 688void
729e4ab9 689DigitList::set(int32_t source)
374ca955 690{
729e4ab9 691 set((int64_t)source);
51004dcb 692 internalSetDouble(source);
374ca955
A
693}
694
695// -------------------------------------
b75a7d8f 696/**
51004dcb 697 * Set an int64, via decnumber
b75a7d8f
A
698 */
699void
729e4ab9 700DigitList::set(int64_t source)
b75a7d8f 701{
729e4ab9
A
702 char str[MAX_DIGITS+2]; // Leave room for sign and trailing nul.
703 formatBase10(source, str);
704 U_ASSERT(uprv_strlen(str) < sizeof(str));
b75a7d8f 705
729e4ab9 706 uprv_decNumberFromString(fDecNumber, str, &fContext);
51004dcb
A
707 internalSetDouble(source);
708}
709
710/**
711 * Set an int64, with no decnumber
712 */
713void
714DigitList::setInteger(int64_t source)
715{
716 fDecNumber=NULL;
717 internalSetInt64(source);
729e4ab9 718}
46f4442e 719
46f4442e 720
729e4ab9
A
721// -------------------------------------
722/**
723 * Set the DigitList from a decimal number string.
724 *
725 * The incoming string _must_ be nul terminated, even though it is arriving
726 * as a StringPiece because that is what the decNumber library wants.
727 * We can get away with this for an internal function; it would not
728 * be acceptable for a public API.
729 */
730void
51004dcb 731DigitList::set(const StringPiece &source, UErrorCode &status, uint32_t /*fastpathBits*/) {
729e4ab9
A
732 if (U_FAILURE(status)) {
733 return;
734 }
735
51004dcb
A
736#if 0
737 if(fastpathBits==(kFastpathOk|kNoDecimal)) {
738 int32_t size = source.size();
739 const char *data = source.data();
740 int64_t r = 0;
741 int64_t m = 1;
742 // fast parse
743 while(size>0) {
744 char ch = data[--size];
745 if(ch=='+') {
746 break;
747 } else if(ch=='-') {
748 r = -r;
749 break;
750 } else {
751 int64_t d = ch-'0';
752 //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m);
753 r+=(d)*m;
754 m *= 10;
755 }
756 }
757 //printf("R=%d\n", r);
758 set(r);
759 } else
760#endif
761 {
762 // Figure out a max number of digits to use during the conversion, and
763 // resize the number up if necessary.
764 int32_t numDigits = source.length();
765 if (numDigits > fContext.digits) {
729e4ab9
A
766 // fContext.digits == fStorage.getCapacity()
767 decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
768 if (t == NULL) {
51004dcb
A
769 status = U_MEMORY_ALLOCATION_ERROR;
770 return;
729e4ab9
A
771 }
772 fDecNumber = t;
773 fContext.digits = numDigits;
51004dcb 774 }
729e4ab9 775
51004dcb
A
776 fContext.status = 0;
777 uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
778 if ((fContext.status & DEC_Conversion_syntax) != 0) {
729e4ab9 779 status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
51004dcb 780 }
729e4ab9 781 }
51004dcb 782 internalClear();
729e4ab9 783}
b75a7d8f
A
784
785/**
786 * Set the digit list to a representation of the given double value.
787 * This method supports both fixed-point and exponential notation.
729e4ab9 788 * @param source Value to be converted.
b75a7d8f
A
789 */
790void
729e4ab9 791DigitList::set(double source)
b75a7d8f
A
792{
793 // for now, simple implementation; later, do proper IEEE stuff
794 char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough)
b75a7d8f 795
4388f060
A
796 // Generate a representation of the form /[+-][0-9].[0-9]+e[+-][0-9]+/
797 // Can also generate /[+-]nan/ or /[+-]inf/
798 // TODO: Use something other than sprintf() here, since it's behavior is somewhat platform specific.
799 // That is why infinity is special cased here.
800 if (uprv_isInfinite(source)) {
801 if (uprv_isNegativeInfinity(source)) {
802 uprv_strcpy(rep,"-inf"); // Handle negative infinity
803 } else {
804 uprv_strcpy(rep,"inf");
805 }
806 } else {
807 sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
808 }
729e4ab9
A
809 U_ASSERT(uprv_strlen(rep) < sizeof(rep));
810
4388f060
A
811 // uprv_decNumberFromString() will parse the string expecting '.' as a
812 // decimal separator, however sprintf() can use ',' in certain locales.
813 // Overwrite a ',' with '.' here before proceeding.
814 char *decimalSeparator = strchr(rep, ',');
815 if (decimalSeparator != NULL) {
816 *decimalSeparator = '.';
817 }
818
729e4ab9
A
819 // Create a decNumber from the string.
820 uprv_decNumberFromString(fDecNumber, rep, &fContext);
821 uprv_decNumberTrim(fDecNumber);
51004dcb 822 internalSetDouble(source);
729e4ab9 823}
b75a7d8f 824
729e4ab9 825// -------------------------------------
b75a7d8f 826
729e4ab9
A
827/*
828 * Multiply
829 * The number will be expanded if need be to retain full precision.
830 * In practice, for formatting, multiply is by 10, 100 or 1000, so more digits
831 * will not be required for this use.
832 */
833void
834DigitList::mult(const DigitList &other, UErrorCode &status) {
835 fContext.status = 0;
836 int32_t requiredDigits = this->digits() + other.digits();
837 if (requiredDigits > fContext.digits) {
838 reduce(); // Remove any trailing zeros
839 int32_t requiredDigits = this->digits() + other.digits();
840 ensureCapacity(requiredDigits, status);
b75a7d8f 841 }
729e4ab9 842 uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
51004dcb 843 internalClear();
729e4ab9 844}
b75a7d8f 845
729e4ab9 846// -------------------------------------
b75a7d8f 847
729e4ab9
A
848/*
849 * Divide
850 * The number will _not_ be expanded for inexact results.
851 * TODO: probably should expand some, for rounding increments that
852 * could add a few digits, e.g. .25, but not expand arbitrarily.
853 */
854void
855DigitList::div(const DigitList &other, UErrorCode &status) {
856 if (U_FAILURE(status)) {
b75a7d8f
A
857 return;
858 }
729e4ab9 859 uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
51004dcb 860 internalClear();
729e4ab9 861}
b75a7d8f 862
729e4ab9 863// -------------------------------------
b75a7d8f 864
729e4ab9
A
865/*
866 * ensureCapacity. Grow the digit storage for the number if it's less than the requested
867 * amount. Never reduce it. Available size is kept in fContext.digits.
868 */
869void
870DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
871 if (U_FAILURE(status)) {
872 return;
b75a7d8f 873 }
729e4ab9
A
874 if (requestedCapacity <= 0) {
875 status = U_ILLEGAL_ARGUMENT_ERROR;
876 return;
877 }
878 if (requestedCapacity > DEC_MAX_DIGITS) {
879 // Don't report an error for requesting too much.
880 // Arithemetic Results will be rounded to what can be supported.
881 // At 999,999,999 max digits, exceeding the limit is not too likely!
882 requestedCapacity = DEC_MAX_DIGITS;
883 }
884 if (requestedCapacity > fContext.digits) {
885 decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
886 if (newBuffer == NULL) {
887 status = U_MEMORY_ALLOCATION_ERROR;
888 return;
889 }
890 fContext.digits = requestedCapacity;
891 fDecNumber = newBuffer;
b75a7d8f
A
892 }
893}
894
895// -------------------------------------
896
897/**
898 * Round the representation to the given number of digits.
899 * @param maximumDigits The maximum number of digits to be shown.
900 * Upon return, count will be less than or equal to maximumDigits.
901 */
46f4442e 902void
b75a7d8f
A
903DigitList::round(int32_t maximumDigits)
904{
729e4ab9
A
905 int32_t savedDigits = fContext.digits;
906 fContext.digits = maximumDigits;
907 uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
908 fContext.digits = savedDigits;
909 uprv_decNumberTrim(fDecNumber);
51004dcb 910 internalClear();
b75a7d8f
A
911}
912
46f4442e 913
729e4ab9
A
914void
915DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
916 trim(); // Remove trailing zeros.
917 if (fDecNumber->exponent >= -maximumFractionDigits) {
918 return;
b75a7d8f 919 }
729e4ab9
A
920 decNumber scale; // Dummy decimal number, but with the desired number of
921 uprv_decNumberZero(&scale); // fraction digits.
922 scale.exponent = -maximumFractionDigits;
923 scale.lsu[0] = 1;
924
925 uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
926 trim();
51004dcb 927 internalClear();
b75a7d8f
A
928}
929
930// -------------------------------------
931
b75a7d8f 932void
729e4ab9
A
933DigitList::toIntegralValue() {
934 uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
b75a7d8f 935}
b75a7d8f 936
729e4ab9
A
937
938// -------------------------------------
b75a7d8f
A
939UBool
940DigitList::isZero() const
941{
729e4ab9 942 return decNumberIsZero(fDecNumber);
b75a7d8f
A
943}
944
b75a7d8f 945U_NAMESPACE_END
46f4442e 946#endif // #if !UCONFIG_NO_FORMATTING
b75a7d8f
A
947
948//eof