]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/text/DigitList.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / text / DigitList.java
1 //##header J2SE15
2 /*
3  *******************************************************************************
4  * Copyright (C) 1996-2009, International Business Machines Corporation and    *
5  * others. All Rights Reserved.                                                *
6  *******************************************************************************
7  */
8 package com.ibm.icu.text;
9
10 import java.math.BigInteger;
11
12 /**
13  * <code>DigitList</code> handles the transcoding between numeric values and
14  * strings of characters.  It only represents non-negative numbers.  The
15  * division of labor between <code>DigitList</code> and
16  * <code>DecimalFormat</code> is that <code>DigitList</code> handles the radix
17  * 10 representation issues and numeric conversion, including rounding;
18  * <code>DecimalFormat</code> handles the locale-specific issues such as
19  * positive and negative representation, digit grouping, decimal point,
20  * currency, and so on.
21  *
22  * <p>A <code>DigitList</code> is a representation of a finite numeric value.
23  * <code>DigitList</code> objects do not represent <code>NaN</code> or infinite
24  * values.  A <code>DigitList</code> value can be converted to a
25  * <code>BigDecimal</code> without loss of precision.  Conversion to other
26  * numeric formats may involve loss of precision, depending on the specific
27  * value.
28  *
29  * <p>The <code>DigitList</code> representation consists of a string of
30  * characters, which are the digits radix 10, from '0' to '9'.  It also has a
31  * base 10 exponent associated with it.  The value represented by a
32  * <code>DigitList</code> object can be computed by mulitplying the fraction
33  * <em>f</em>, where 0 <= <em>f</em> < 1, derived by placing all the digits of
34  * the list to the right of the decimal point, by 10^exponent.
35  *
36  * @see java.util.Locale
37  * @see java.text.Format
38  * @see NumberFormat
39  * @see DecimalFormat
40  * @see java.text.ChoiceFormat
41  * @see java.text.MessageFormat
42  * @version      1.18 08/12/98
43  * @author       Mark Davis, Alan Liu
44  * */
45 final class DigitList {
46     /**
47      * The maximum number of significant digits in an IEEE 754 double, that
48      * is, in a Java double.  This must not be increased, or garbage digits
49      * will be generated, and should not be decreased, or accuracy will be lost.
50      */
51     public static final int MAX_LONG_DIGITS = 19; // == Long.toString(Long.MAX_VALUE).length()
52     public static final int DBL_DIG = 17;
53
54     /**
55      * These data members are intentionally public and can be set directly.
56      *
57      * The value represented is given by placing the decimal point before
58      * digits[decimalAt].  If decimalAt is < 0, then leading zeros between
59      * the decimal point and the first nonzero digit are implied.  If decimalAt
60      * is > count, then trailing zeros between the digits[count-1] and the
61      * decimal point are implied.
62      *
63      * Equivalently, the represented value is given by f * 10^decimalAt.  Here
64      * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to
65      * the right of the decimal.
66      *
67      * DigitList is normalized, so if it is non-zero, figits[0] is non-zero.  We
68      * don't allow denormalized numbers because our exponent is effectively of
69      * unlimited magnitude.  The count value contains the number of significant
70      * digits present in digits[].
71      *
72      * Zero is represented by any DigitList with count == 0 or with each digits[i]
73      * for all i <= count == '0'.
74      */
75     public int decimalAt = 0;
76     public int count = 0;
77     public byte[] digits = new byte[MAX_LONG_DIGITS];
78
79     private final void ensureCapacity(int digitCapacity, int digitsToCopy) {
80         if (digitCapacity > digits.length) {
81             byte[] newDigits = new byte[digitCapacity * 2];
82             System.arraycopy(digits, 0, newDigits, 0, digitsToCopy);
83             digits = newDigits;
84         }
85     }
86
87     /**
88      * Return true if the represented number is zero.
89      */
90     boolean isZero()
91     {
92         for (int i=0; i<count; ++i) if (digits[i] != '0') return false;
93         return true;
94     }
95
96 // Unused as of ICU 2.6 - alan
97 //    /**
98 //     * Clears out the digits.
99 //     * Use before appending them.
100 //     * Typically, you set a series of digits with append, then at the point
101 //     * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count;
102 //     * then go on appending digits.
103 //     */
104 //    public void clear () {
105 //        decimalAt = 0;
106 //        count = 0;
107 //    }
108
109     /**
110      * Appends digits to the list.
111      */
112     public void append (int digit) {
113         ensureCapacity(count+1, count);
114         digits[count++] = (byte) digit;
115     }
116     /**
117      * Utility routine to get the value of the digit list
118      * If (count == 0) this throws a NumberFormatException, which
119      * mimics Long.parseLong().
120      */
121     public final double getDouble() {
122         if (count == 0) return 0.0;
123         StringBuffer temp = new StringBuffer(count);
124         temp.append('.');
125         for (int i = 0; i < count; ++i) temp.append((char)(digits[i]));
126         temp.append('E');
127         temp.append(Integer.toString(decimalAt));
128         return Double.valueOf(temp.toString()).doubleValue();
129         // long value = Long.parseLong(temp.toString());
130         // return (value * Math.pow(10, decimalAt - count));
131     }
132
133     /**
134      * Utility routine to get the value of the digit list.
135      * If (count == 0) this returns 0, unlike Long.parseLong().
136      */
137     public final long getLong() {
138         // for now, simple implementation; later, do proper IEEE native stuff
139
140         if (count == 0) return 0;
141
142         // We have to check for this, because this is the one NEGATIVE value
143         // we represent.  If we tried to just pass the digits off to parseLong,
144         // we'd get a parse failure.
145         if (isLongMIN_VALUE()) return Long.MIN_VALUE;
146
147         StringBuffer temp = new StringBuffer(count);
148         for (int i = 0; i < decimalAt; ++i)
149         {
150             temp.append((i < count) ? (char)(digits[i]) : '0');
151         }
152         return Long.parseLong(temp.toString());
153     }
154
155     /**
156      * Return a <code>BigInteger</code> representing the value stored in this
157      * <code>DigitList</code>.  This method assumes that this object contains
158      * an integral value; if not, it will return an incorrect value.
159      * [bnf]
160      * @param isPositive determines the sign of the returned result
161      * @return the value of this object as a <code>BigInteger</code>
162      */
163     public BigInteger getBigInteger(boolean isPositive) {
164         if (isZero()) return BigInteger.valueOf(0);
165         if (false) {
166             StringBuffer stringRep = new StringBuffer(count);
167             if (!isPositive) {
168                 stringRep.append('-');
169             }
170             for (int i=0; i<count; ++i) {
171                 stringRep.append((char) digits[i]);
172             }
173             int d = decimalAt;
174             while (d-- > count) {
175                 stringRep.append('0');
176             }
177             return new BigInteger(stringRep.toString());
178         } else {
179             int len = decimalAt > count ? decimalAt : count;
180             if (!isPositive) {
181                 len += 1;
182             }
183             char[] text = new char[len];
184             int n = 0;
185             if (!isPositive) {
186                 text[0] = '-';
187                 for (int i = 0; i < count; ++i) {
188                     text[i+1] = (char)digits[i];
189                 }
190                 n = count+1;
191             } else {
192                 for (int i = 0; i < count; ++i) {
193                     text[i] = (char)digits[i];
194                 }
195                 n = count;
196             }
197             for (int i = n; i < text.length; ++i) {
198                 text[i] = '0';
199             } 
200             return new BigInteger(new String(text));
201         }
202     }
203
204     private String getStringRep(boolean isPositive) {
205         if (isZero()) return "0";
206         StringBuffer stringRep = new StringBuffer(count+1);
207         if (!isPositive) {
208             stringRep.append('-');
209         }
210         int d = decimalAt;
211         if (d < 0) {
212             stringRep.append('.');
213             while (d < 0) {
214                 stringRep.append('0');
215                 ++d;
216             }
217             d = -1;
218         }
219         for (int i=0; i<count; ++i) {
220             if (d == i) {
221                 stringRep.append('.');
222             }
223             stringRep.append((char) digits[i]);
224         }
225         while (d-- > count) {
226             stringRep.append('0');
227         }
228         return stringRep.toString();
229     }
230
231 //#if defined(FOUNDATION10)
232 //#else
233     /**
234      * Return a <code>BigDecimal</code> representing the value stored in this
235      * <code>DigitList</code>.
236      * [bnf]
237      * @param isPositive determines the sign of the returned result
238      * @return the value of this object as a <code>BigDecimal</code>
239      */
240     public java.math.BigDecimal getBigDecimal(boolean isPositive) {
241         if (isZero()) {
242             return java.math.BigDecimal.valueOf(0);
243         }
244         // if exponential notion is negative,
245         // we prefer to use BigDecimal constructor with scale,
246         // because it works better when extremely small value
247         // is used.  See #5698.
248         long scale = (long)count - (long)decimalAt;
249         if (scale > 0) {
250             int numDigits = count;
251             if (scale > (long)Integer.MAX_VALUE) {
252                 // try to reduce the scale
253                 long numShift = scale - (long)Integer.MAX_VALUE;
254                 if (numShift < count) {
255                     numDigits -= numShift;
256                 } else {
257                     // fallback to 0
258                     return new java.math.BigDecimal(0);
259                 }
260             }
261             StringBuffer significantDigits = new StringBuffer(numDigits + 1);
262             if (!isPositive) {
263                 significantDigits.append('-');
264             }
265             for (int i = 0; i < numDigits; i++) {
266                 significantDigits.append((char)digits[i]);
267             }
268             BigInteger unscaledVal = new BigInteger(significantDigits.toString());
269             return new java.math.BigDecimal(unscaledVal, (int)scale);
270         } else {
271             // We should be able to use a negative scale value for a positive exponential
272             // value on JDK1.5.  But it is not supported by older JDK.  So, for now,
273             // we always use BigDecimal constructor which takes String.
274             return new java.math.BigDecimal(getStringRep(isPositive));
275         }
276     }
277 //#endif
278
279     /**
280      * Return an <code>ICU BigDecimal</code> representing the value stored in this
281      * <code>DigitList</code>.
282      * [bnf]
283      * @param isPositive determines the sign of the returned result
284      * @return the value of this object as a <code>BigDecimal</code>
285      */
286     public com.ibm.icu.math.BigDecimal getBigDecimalICU(boolean isPositive) {
287         if (isZero()) {
288             return com.ibm.icu.math.BigDecimal.valueOf(0);
289         }
290         // if exponential notion is negative,
291         // we prefer to use BigDecimal constructor with scale,
292         // because it works better when extremely small value
293         // is used.  See #5698.
294         long scale = (long)count - (long)decimalAt;
295         if (scale > 0) {
296             int numDigits = count;
297             if (scale > (long)Integer.MAX_VALUE) {
298                 // try to reduce the scale
299                 long numShift = scale - (long)Integer.MAX_VALUE;
300                 if (numShift < count) {
301                     numDigits -= numShift;
302                 } else {
303                     // fallback to 0
304                     return new com.ibm.icu.math.BigDecimal(0);
305                 }
306             }
307             StringBuffer significantDigits = new StringBuffer(numDigits + 1);
308             if (!isPositive) {
309                 significantDigits.append('-');
310             }
311             for (int i = 0; i < numDigits; i++) {
312                 significantDigits.append((char)digits[i]);
313             }
314             BigInteger unscaledVal = new BigInteger(significantDigits.toString());
315             return new com.ibm.icu.math.BigDecimal(unscaledVal, (int)scale);
316         } else {
317             return new com.ibm.icu.math.BigDecimal(getStringRep(isPositive));
318         }
319     }
320
321     /**
322      * Return whether or not this objects represented value is an integer.
323      * [bnf]
324      * @return true if the represented value of this object is an integer
325      */
326     boolean isIntegral() {
327         // Trim trailing zeros.  This does not change the represented value.
328         while (count > 0 && digits[count - 1] == (byte)'0') --count;
329         return count == 0 || decimalAt >= count;
330     }
331
332 // Unused as of ICU 2.6 - alan
333 //    /**
334 //     * Return true if the number represented by this object can fit into
335 //     * a long.
336 //     */
337 //    boolean fitsIntoLong(boolean isPositive)
338 //    {
339 //        // Figure out if the result will fit in a long.  We have to
340 //        // first look for nonzero digits after the decimal point;
341 //        // then check the size.  If the digit count is 18 or less, then
342 //        // the value can definitely be represented as a long.  If it is 19
343 //        // then it may be too large.
344 //
345 //        // Trim trailing zeros.  This does not change the represented value.
346 //        while (count > 0 && digits[count - 1] == (byte)'0') --count;
347 //
348 //        if (count == 0) {
349 //            // Positive zero fits into a long, but negative zero can only
350 //            // be represented as a double. - bug 4162852
351 //            return isPositive;
352 //        }
353 //
354 //        if (decimalAt < count || decimalAt > MAX_LONG_DIGITS) return false;
355 //
356 //        if (decimalAt < MAX_LONG_DIGITS) return true;
357 //
358 //        // At this point we have decimalAt == count, and count == MAX_LONG_DIGITS.
359 //        // The number will overflow if it is larger than 9223372036854775807
360 //        // or smaller than -9223372036854775808.
361 //        for (int i=0; i<count; ++i)
362 //        {
363 //            byte dig = digits[i], max = LONG_MIN_REP[i];
364 //            if (dig > max) return false;
365 //            if (dig < max) return true;
366 //        }
367 //
368 //        // At this point the first count digits match.  If decimalAt is less
369 //        // than count, then the remaining digits are zero, and we return true.
370 //        if (count < decimalAt) return true;
371 //
372 //        // Now we have a representation of Long.MIN_VALUE, without the leading
373 //        // negative sign.  If this represents a positive value, then it does
374 //        // not fit; otherwise it fits.
375 //        return !isPositive;
376 //    }
377
378 // Unused as of ICU 2.6 - alan
379 //    /**
380 //     * Set the digit list to a representation of the given double value.
381 //     * This method supports fixed-point notation.
382 //     * @param source Value to be converted; must not be Inf, -Inf, Nan,
383 //     * or a value <= 0.
384 //     * @param maximumFractionDigits The most fractional digits which should
385 //     * be converted.
386 //     */
387 //    public final void set(double source, int maximumFractionDigits)
388 //    {
389 //        set(source, maximumFractionDigits, true);
390 //    }
391
392     /**
393      * Set the digit list to a representation of the given double value.
394      * This method supports both fixed-point and exponential notation.
395      * @param source Value to be converted; must not be Inf, -Inf, Nan,
396      * or a value <= 0.
397      * @param maximumDigits The most fractional or total digits which should
398      * be converted.
399      * @param fixedPoint If true, then maximumDigits is the maximum
400      * fractional digits to be converted.  If false, total digits.
401      */
402     final void set(double source, int maximumDigits, boolean fixedPoint)
403     {
404         if (source == 0) source = 0;
405         // Generate a representation of the form DDDDD, DDDDD.DDDDD, or
406         // DDDDDE+/-DDDDD.
407         String rep = Double.toString(source);
408
409         set(rep, MAX_LONG_DIGITS);
410
411         if (fixedPoint) {
412             // The negative of the exponent represents the number of leading
413             // zeros between the decimal and the first non-zero digit, for
414             // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2).  If this
415             // is more than the maximum fraction digits, then we have an underflow
416             // for the printed representation.
417             if (-decimalAt > maximumDigits) {
418                 count = 0;
419                 return;
420             } else if (-decimalAt == maximumDigits) {
421                 if (shouldRoundUp(0)) {
422                     count = 1;
423                     ++decimalAt;
424                     digits[0] = (byte)'1';
425                 } else {
426                     count = 0;
427                 }
428                 return;
429             }
430             // else fall through
431         }
432
433         // Eliminate trailing zeros.
434         while (count > 1 && digits[count - 1] == '0')
435             --count;
436
437         // Eliminate digits beyond maximum digits to be displayed.
438         // Round up if appropriate.
439         round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
440     }
441
442     /**
443      * Given a string representation of the form DDDDD, DDDDD.DDDDD,
444      * or DDDDDE+/-DDDDD, set this object's value to it.  Ignore
445      * any leading '-'.
446      */
447     private void set(String rep, int maxCount) {
448         decimalAt = -1;
449         count = 0;
450         int exponent = 0;
451         // Number of zeros between decimal point and first non-zero digit after
452         // decimal point, for numbers < 1.
453         int leadingZerosAfterDecimal = 0;
454         boolean nonZeroDigitSeen = false;
455         // Skip over leading '-'
456         int i=0;
457         if (rep.charAt(i) == '-') {
458             ++i;
459         }
460         for (; i < rep.length(); ++i) {
461             char c = rep.charAt(i);
462             if (c == '.') {
463                 decimalAt = count;
464             } else if (c == 'e' || c == 'E') {
465                 ++i;
466                 // Integer.parseInt doesn't handle leading '+' signs
467                 if (rep.charAt(i) == '+') {
468                     ++i;
469                 }
470                 exponent = Integer.valueOf(rep.substring(i)).intValue();
471                 break;
472             } else if (count < maxCount) {
473                 if (!nonZeroDigitSeen) {
474                     nonZeroDigitSeen = (c != '0');
475                     if (!nonZeroDigitSeen && decimalAt != -1) {
476                         ++leadingZerosAfterDecimal;
477                     }
478                 }
479
480                 if (nonZeroDigitSeen) {
481                     ensureCapacity(count+1, count);
482                     digits[count++] = (byte)c;
483                 }
484             }
485         }
486         if (decimalAt == -1) {
487             decimalAt = count;
488         }
489         decimalAt += exponent - leadingZerosAfterDecimal;
490     }
491
492     /**
493      * Return true if truncating the representation to the given number
494      * of digits will result in an increment to the last digit.  This
495      * method implements half-even rounding, the default rounding mode.
496      * [bnf]
497      * @param maximumDigits the number of digits to keep, from 0 to
498      * <code>count-1</code>.  If 0, then all digits are rounded away, and
499      * this method returns true if a one should be generated (e.g., formatting
500      * 0.09 with "#.#").
501      * @return true if digit <code>maximumDigits-1</code> should be
502      * incremented
503      */
504     private boolean shouldRoundUp(int maximumDigits) {
505         // variable not used boolean increment = false;
506         // Implement IEEE half-even rounding
507         /*Bug 4243108
508           format(0.0) gives "0.1" if preceded by parse("99.99") [Richard/GCL]
509         */
510         if (maximumDigits < count) {
511             if (digits[maximumDigits] > '5') {
512                 return true;
513             } else if (digits[maximumDigits] == '5' ) {
514                 for (int i=maximumDigits+1; i<count; ++i) {
515                     if (digits[i] != '0') {
516                         return true;
517                     }
518                 }
519                 return maximumDigits > 0 && (digits[maximumDigits-1] % 2 != 0);
520             }
521         }
522         return false;
523     }
524
525     /**
526      * Round the representation to the given number of digits.
527      * @param maximumDigits The maximum number of digits to be shown.
528      * Upon return, count will be less than or equal to maximumDigits.
529      * This now performs rounding when maximumDigits is 0, formerly it did not.
530      */
531     public final void round(int maximumDigits) {        
532         // Eliminate digits beyond maximum digits to be displayed.
533         // Round up if appropriate.
534         // [bnf] rewritten to fix 4179818
535         if (maximumDigits >= 0 && maximumDigits < count) {
536             if (shouldRoundUp(maximumDigits)) {
537                 // Rounding up involves incrementing digits from LSD to MSD.
538                 // In most cases this is simple, but in a worst case situation
539                 // (9999..99) we have to adjust the decimalAt value.
540                 for (;;)
541                 {
542                     --maximumDigits;
543                     if (maximumDigits < 0)
544                     {
545                         // We have all 9's, so we increment to a single digit
546                         // of one and adjust the exponent.
547                         digits[0] = (byte) '1';
548                         ++decimalAt;
549                         maximumDigits = 0; // Adjust the count
550                         break;
551                     }
552
553                     ++digits[maximumDigits];
554                     if (digits[maximumDigits] <= '9') break;
555                     // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
556                 }
557                 ++maximumDigits; // Increment for use as count
558             }
559             count = maximumDigits;
560             /*Bug 4217661 DecimalFormat formats 1.001 to "1.00" instead of "1"
561               Eliminate trailing zeros. [Richard/GCL]
562             */
563             while (count > 1 && digits[count-1] == '0') {
564                 --count;
565             } //[Richard/GCL]
566         }
567     }
568
569     /**
570      * Utility routine to set the value of the digit list from a long
571      */
572     public final void set(long source)
573     {
574         set(source, 0);
575     }
576
577     /**
578      * Set the digit list to a representation of the given long value.
579      * @param source Value to be converted; must be >= 0 or ==
580      * Long.MIN_VALUE.
581      * @param maximumDigits The most digits which should be converted.
582      * If maximumDigits is lower than the number of significant digits
583      * in source, the representation will be rounded.  Ignored if <= 0.
584      */
585     public final void set(long source, int maximumDigits)
586     {
587         // This method does not expect a negative number. However,
588         // "source" can be a Long.MIN_VALUE (-9223372036854775808),
589         // if the number being formatted is a Long.MIN_VALUE.  In that
590         // case, it will be formatted as -Long.MIN_VALUE, a number
591         // which is outside the legal range of a long, but which can
592         // be represented by DigitList.
593         // [NEW] Faster implementation
594         if (source <= 0) {
595             if (source == Long.MIN_VALUE) {
596                 decimalAt = count = MAX_LONG_DIGITS;
597                 System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
598             } else {
599                 count = 0;
600                 decimalAt = 0;
601             }
602         } else {
603             int left = MAX_LONG_DIGITS;
604             int right;
605             while (source > 0) {
606                 digits[--left] = (byte) (((long) '0') + (source % 10));
607                 source /= 10;
608             }
609             decimalAt = MAX_LONG_DIGITS-left;
610             // Don't copy trailing zeros
611             // we are guaranteed that there is at least one non-zero digit,
612             // so we don't have to check lower bounds
613             for (right = MAX_LONG_DIGITS - 1; digits[right] == (byte) '0'; --right) {}
614             count = right - left + 1;
615             System.arraycopy(digits, left, digits, 0, count);
616         }        
617         if (maximumDigits > 0) round(maximumDigits);
618     }
619
620     /**
621      * Set the digit list to a representation of the given BigInteger value.
622      * [bnf]
623      * @param source Value to be converted
624      * @param maximumDigits The most digits which should be converted.
625      * If maximumDigits is lower than the number of significant digits
626      * in source, the representation will be rounded.  Ignored if <= 0.
627      */
628     public final void set(BigInteger source, int maximumDigits) {
629         String stringDigits = source.toString();
630
631         count = decimalAt = stringDigits.length();
632
633         // Don't copy trailing zeros
634         while (count > 1 && stringDigits.charAt(count - 1) == '0') --count;
635
636         int offset = 0;
637         if (stringDigits.charAt(0) == '-') {
638             ++offset;
639             --count;
640             --decimalAt;
641         }
642
643         ensureCapacity(count, 0);
644         for (int i = 0; i < count; ++i) {
645             digits[i] = (byte) stringDigits.charAt(i + offset);
646         }
647
648         if (maximumDigits > 0) round(maximumDigits);
649     }
650
651     /**
652      * Internal method that sets this digit list to represent the
653      * given value.  The value is given as a String of the format
654      * returned by BigDecimal.
655      * @param stringDigits value to be represented with the following
656      * syntax, expressed as a regular expression: -?\d*.?\d*
657      * Must not be an empty string.
658      * @param maximumDigits The most digits which should be converted.
659      * If maximumDigits is lower than the number of significant digits
660      * in source, the representation will be rounded.  Ignored if <= 0.
661      * @param fixedPoint If true, then maximumDigits is the maximum
662      * fractional digits to be converted.  If false, total digits.
663      */
664     private void setBigDecimalDigits(String stringDigits,
665                                      int maximumDigits, boolean fixedPoint) {
666 //|        // Find the first non-zero digit, the decimal, and the last non-zero digit.
667 //|        int first=-1, last=stringDigits.length()-1, decimal=-1;
668 //|        for (int i=0; (first<0 || decimal<0) && i<=last; ++i) {
669 //|            char c = stringDigits.charAt(i);
670 //|            if (c == '.') {
671 //|                decimal = i;
672 //|            } else if (first < 0 && (c >= '1' && c <= '9')) {
673 //|                first = i;
674 //|            }
675 //|        }
676 //|
677 //|        if (first < 0) {
678 //|            clear();
679 //|            return;
680 //|        }
681 //|
682 //|        // At this point we know there is at least one non-zero digit, so the
683 //|        // following loop is safe.
684 //|        for (;;) {
685 //|            char c = stringDigits.charAt(last);
686 //|            if (c != '0' && c != '.') {
687 //|                break;
688 //|            }
689 //|            --last;
690 //|        }
691 //|
692 //|        if (decimal < 0) {
693 //|            decimal = stringDigits.length();
694 //|        }
695 //|
696 //|        count = last - first;
697 //|        if (decimal < first || decimal > last) {
698 //|            ++count;
699 //|        }
700 //|        decimalAt = decimal - first;
701 //|        if (decimalAt < 0) {
702 //|            ++decimalAt;
703 //|        }
704 //|
705 //|        ensureCapacity(count, 0);
706 //|        for (int i = 0; i < count; ++i) {
707 //|            digits[i] = (byte) stringDigits.charAt(first++);
708 //|            if (first == decimal) {
709 //|                ++first;
710 //|            }
711 //|        }
712
713         // The maxDigits here could also be Integer.MAX_VALUE
714         set(stringDigits, stringDigits.length());
715
716         // Eliminate digits beyond maximum digits to be displayed.
717         // Round up if appropriate.
718     // {dlf} Some callers depend on passing '0' to round to mean 'don't round', but
719     // rather than pass that information explicitly, we rely on some magic with maximumDigits
720     // and decimalAt.  Unfortunately, this is no good, because there are cases where maximumDigits
721     // is zero and we do want to round, e.g. BigDecimal values -1 < x < 1.  So since round
722     // changed to perform rounding when the argument is 0, we now force the argument
723     // to -1 in the situations where it matters.
724         round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits == 0 ? -1 : maximumDigits);
725     }
726
727 //#if defined(FOUNDATION10)
728 //#else
729     /**
730      * Set the digit list to a representation of the given BigDecimal value.
731      * [bnf]
732      * @param source Value to be converted
733      * @param maximumDigits The most digits which should be converted.
734      * If maximumDigits is lower than the number of significant digits
735      * in source, the representation will be rounded.  Ignored if <= 0.
736      * @param fixedPoint If true, then maximumDigits is the maximum
737      * fractional digits to be converted.  If false, total digits.
738      */
739     public final void set(java.math.BigDecimal source,
740                           int maximumDigits, boolean fixedPoint) {
741         setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
742     }
743 //#endif
744
745     /*
746      * Set the digit list to a representation of the given BigDecimal value.
747      * [bnf]
748      * @param source Value to be converted
749      * @param maximumDigits The most digits which should be converted.
750      * If maximumDigits is lower than the number of significant digits
751      * in source, the representation will be rounded.  Ignored if <= 0.
752      * @param fixedPoint If true, then maximumDigits is the maximum
753      * fractional digits to be converted.  If false, total digits.
754      */
755     public final void set(com.ibm.icu.math.BigDecimal source,
756                           int maximumDigits, boolean fixedPoint) {
757         setBigDecimalDigits(source.toString(), maximumDigits, fixedPoint);
758     }
759
760     /**
761      * Returns true if this DigitList represents Long.MIN_VALUE;
762      * false, otherwise.  This is required so that getLong() works.
763      */
764     private boolean isLongMIN_VALUE()
765     {
766         if (decimalAt != count || count != MAX_LONG_DIGITS)
767             return false;
768
769             for (int i = 0; i < count; ++i)
770         {
771             if (digits[i] != LONG_MIN_REP[i]) return false;
772         }
773
774         return true;
775     }
776
777     private static byte[] LONG_MIN_REP;
778
779     static
780     {
781         // Store the representation of LONG_MIN without the leading '-'
782         String s = Long.toString(Long.MIN_VALUE);
783         LONG_MIN_REP = new byte[MAX_LONG_DIGITS];
784         for (int i=0; i < MAX_LONG_DIGITS; ++i)
785         {
786             LONG_MIN_REP[i] = (byte)s.charAt(i + 1);
787         }
788     }
789
790 // Unused -- Alan 2003-05
791 //    /**
792 //     * Return the floor of the log base 10 of a given double.
793 //     * This method compensates for inaccuracies which arise naturally when
794 //     * computing logs, and always give the correct value.  The parameter
795 //     * must be positive and finite.
796 //     */
797 //    private static final int log10(double d)
798 //    {
799 //        // The reason this routine is needed is that simply taking the
800 //        // log and dividing by log10 yields a result which may be off
801 //        // by 1 due to rounding errors.  For example, the naive log10
802 //        // of 1.0e300 taken this way is 299, rather than 300.
803 //        double log10 = Math.log(d) / LOG10;
804 //        int ilog10 = (int)Math.floor(log10);
805 //        // Positive logs could be too small, e.g. 0.99 instead of 1.0
806 //        if (log10 > 0 && d >= Math.pow(10, ilog10 + 1))
807 //        {
808 //            ++ilog10;
809 //        }
810 //        // Negative logs could be too big, e.g. -0.99 instead of -1.0
811 //        else if (log10 < 0 && d < Math.pow(10, ilog10))
812 //        {
813 //            --ilog10;
814 //        }
815 //        return ilog10;
816 //    }
817 //
818 //    private static final double LOG10 = Math.log(10.0);
819
820     // (The following boilerplate methods are currently not called,
821     // and cannot be called by tests since this class is
822     // package-private.  The methods may be useful in the future, so
823     // we do not delete them.  2003-06-11 ICU 2.6 Alan)
824     ///CLOVER:OFF
825     /**
826      * equality test between two digit lists.
827      */
828     public boolean equals(Object obj) {
829         if (this == obj)                      // quick check
830             return true;
831         if (!(obj instanceof DigitList))         // (1) same object?
832             return false;
833         DigitList other = (DigitList) obj;
834         if (count != other.count ||
835         decimalAt != other.decimalAt)
836             return false;
837         for (int i = 0; i < count; i++)
838             if (digits[i] != other.digits[i])
839                 return false;
840         return true;
841     }
842
843     /**
844      * Generates the hash code for the digit list.
845      */
846     public int hashCode() {
847         int hashcode = decimalAt;
848
849         for (int i = 0; i < count; i++)
850             hashcode = hashcode * 37 + digits[i];
851
852         return hashcode;
853     }
854
855     public String toString()
856     {
857         if (isZero()) return "0";
858         StringBuffer buf = new StringBuffer("0.");
859         for (int i=0; i<count; ++i) buf.append((char)digits[i]);
860         buf.append("x10^");
861         buf.append(decimalAt);
862         return buf.toString();
863     }
864     ///CLOVER:ON
865 }