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