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