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