Merge "Port openJdk8 java.lang package, part 2"
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 5809da3..7e34d44 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -25,6 +25,7 @@
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Locale;
import junit.framework.TestCase;
@@ -547,4 +548,48 @@
assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
}
+
+ public void testJoin_CharSequenceArray() {
+ assertEquals("", String.join("-"));
+ assertEquals("", String.join("-", ""));
+ assertEquals("foo", String.join("-", "foo"));
+ assertEquals("foo---bar---boo", String.join("---", "foo", "bar", "boo"));
+ assertEquals("foobarboo", String.join("", "foo", "bar", "boo"));
+ assertEquals("null-null", String.join("-", null, null));
+ assertEquals("¯\\_(ツ)_/¯", String.join("(ツ)", "¯\\_", "_/¯"));
+ }
+
+ public void testJoin_CharSequenceArray_NPE() {
+ try {
+ String.join(null, "foo", "bar");
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ public void testJoin_Iterable() {
+ ArrayList<String> iterable = new ArrayList<>();
+ assertEquals("", String.join("-", iterable));
+
+ iterable.add("foo");
+ assertEquals("foo", String.join("-", iterable));
+
+ iterable.add("bar");
+ assertEquals("foo...bar", String.join("...", iterable));
+
+ iterable.add("foo");
+ assertEquals("foo-bar-foo", String.join("-", iterable));
+ assertEquals("foobarfoo", String.join("", iterable));
+ }
+
+ public void testJoin_Iterable_NPE() {
+ try {
+ String.join(null, new ArrayList<String>());
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ String.join("-", (Iterable<String>)null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
}
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
old mode 100755
new mode 100644
index aa71ca4..383a358
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package java.lang;
+import sun.misc.FloatingDecimal;
import java.util.Arrays;
/**
@@ -35,12 +36,16 @@
* particular sequence of characters, but the length and content of the
* sequence can be changed through certain method calls.
*
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
* @author Michael McCloskey
* @author Martin Buchholz
* @author Ulf Zibis
* @since 1.5
*/
-abstract class AbstractStringBuilder implements CharSequence {
+abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
@@ -70,6 +75,7 @@
* @return the length of the sequence of characters currently
* represented by this object
*/
+ @Override
public int length() {
return count;
}
@@ -91,11 +97,13 @@
* array is allocated with greater capacity. The new capacity is the
* larger of:
* <ul>
- * <li>The <code>minimumCapacity</code> argument.
- * <li>Twice the old capacity, plus <code>2</code>.
+ * <li>The {@code minimumCapacity} argument.
+ * <li>Twice the old capacity, plus {@code 2}.
* </ul>
- * If the <code>minimumCapacity</code> argument is nonpositive, this
+ * If the {@code minimumCapacity} argument is nonpositive, this
* method takes no action and simply returns.
+ * Note that subsequent operations on this object can reduce the
+ * actual capacity below that requested here.
*
* @param minimumCapacity the minimum desired capacity.
*/
@@ -108,7 +116,7 @@
* This method has the same contract as ensureCapacity, but is
* never synchronized.
*/
- void ensureCapacityInternal(int minimumCapacity) {
+ private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
@@ -147,26 +155,26 @@
* Sets the length of the character sequence.
* The sequence is changed to a new character sequence
* whose length is specified by the argument. For every nonnegative
- * index <i>k</i> less than <code>newLength</code>, the character at
+ * index <i>k</i> less than {@code newLength}, the character at
* index <i>k</i> in the new character sequence is the same as the
* character at index <i>k</i> in the old sequence if <i>k</i> is less
* than the length of the old character sequence; otherwise, it is the
- * null character <code>'\u0000'</code>.
+ * null character {@code '\u005Cu0000'}.
*
- * In other words, if the <code>newLength</code> argument is less than
+ * In other words, if the {@code newLength} argument is less than
* the current length, the length is changed to the specified length.
* <p>
- * If the <code>newLength</code> argument is greater than or equal
+ * If the {@code newLength} argument is greater than or equal
* to the current length, sufficient null characters
- * (<code>'\u0000'</code>) are appended so that
- * length becomes the <code>newLength</code> argument.
+ * ({@code '\u005Cu0000'}) are appended so that
+ * length becomes the {@code newLength} argument.
* <p>
- * The <code>newLength</code> argument must be greater than or equal
- * to <code>0</code>.
+ * The {@code newLength} argument must be greater than or equal
+ * to {@code 0}.
*
* @param newLength the new length
* @throws IndexOutOfBoundsException if the
- * <code>newLength</code> argument is negative.
+ * {@code newLength} argument is negative.
*/
public void setLength(int newLength) {
if (newLength < 0)
@@ -174,30 +182,30 @@
ensureCapacityInternal(newLength);
if (count < newLength) {
- for (; count < newLength; count++)
- value[count] = '\0';
- } else {
- count = newLength;
+ Arrays.fill(value, count, newLength, '\0');
}
+
+ count = newLength;
}
/**
- * Returns the <code>char</code> value in this sequence at the specified index.
- * The first <code>char</code> value is at index <code>0</code>, the next at index
- * <code>1</code>, and so on, as in array indexing.
+ * Returns the {@code char} value in this sequence at the specified index.
+ * The first {@code char} value is at index {@code 0}, the next at index
+ * {@code 1}, and so on, as in array indexing.
* <p>
* The index argument must be greater than or equal to
- * <code>0</code>, and less than the length of this sequence.
+ * {@code 0}, and less than the length of this sequence.
*
- * <p>If the <code>char</code> value specified by the index is a
+ * <p>If the {@code char} value specified by the index is a
* <a href="Character.html#unicode">surrogate</a>, the surrogate
* value is returned.
*
- * @param index the index of the desired <code>char</code> value.
- * @return the <code>char</code> value at the specified index.
- * @throws IndexOutOfBoundsException if <code>index</code> is
- * negative or greater than or equal to <code>length()</code>.
+ * @param index the index of the desired {@code char} value.
+ * @return the {@code char} value at the specified index.
+ * @throws IndexOutOfBoundsException if {@code index} is
+ * negative or greater than or equal to {@code length()}.
*/
+ @Override
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
@@ -206,22 +214,22 @@
/**
* Returns the character (Unicode code point) at the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>0</code> to
- * {@link #length()}<code> - 1</code>.
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 0} to
+ * {@link #length()}{@code - 1}.
*
- * <p> If the <code>char</code> value specified at the given index
+ * <p> If the {@code char} value specified at the given index
* is in the high-surrogate range, the following index is less
* than the length of this sequence, and the
- * <code>char</code> value at the following index is in the
+ * {@code char} value at the following index is in the
* low-surrogate range, then the supplementary code point
* corresponding to this surrogate pair is returned. Otherwise,
- * the <code>char</code> value at the given index is returned.
+ * the {@code char} value at the given index is returned.
*
- * @param index the index to the <code>char</code> values
+ * @param index the index to the {@code char} values
* @return the code point value of the character at the
- * <code>index</code>
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * {@code index}
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* sequence.
*/
@@ -229,27 +237,27 @@
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
- return Character.codePointAt(value, index);
+ return Character.codePointAtImpl(value, index, count);
}
/**
* Returns the character (Unicode code point) before the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>1</code> to {@link
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 1} to {@link
* #length()}.
*
- * <p> If the <code>char</code> value at <code>(index - 1)</code>
- * is in the low-surrogate range, <code>(index - 2)</code> is not
- * negative, and the <code>char</code> value at <code>(index -
- * 2)</code> is in the high-surrogate range, then the
+ * <p> If the {@code char} value at {@code (index - 1)}
+ * is in the low-surrogate range, {@code (index - 2)} is not
+ * negative, and the {@code char} value at {@code (index -
+ * 2)} is in the high-surrogate range, then the
* supplementary code point value of the surrogate pair is
- * returned. If the <code>char</code> value at <code>index -
- * 1</code> is an unpaired low-surrogate or a high-surrogate, the
+ * returned. If the {@code char} value at {@code index -
+ * 1} is an unpaired low-surrogate or a high-surrogate, the
* surrogate value is returned.
*
* @param index the index following the code point that should be returned
* @return the Unicode code point value before the given index.
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is less than 1 or greater than the length
* of this sequence.
*/
@@ -258,28 +266,28 @@
if ((i < 0) || (i >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
- return Character.codePointBefore(value, index);
+ return Character.codePointBeforeImpl(value, index, 0);
}
/**
* Returns the number of Unicode code points in the specified text
* range of this sequence. The text range begins at the specified
- * <code>beginIndex</code> and extends to the <code>char</code> at
- * index <code>endIndex - 1</code>. Thus the length (in
- * <code>char</code>s) of the text range is
- * <code>endIndex-beginIndex</code>. Unpaired surrogates within
+ * {@code beginIndex} and extends to the {@code char} at
+ * index {@code endIndex - 1}. Thus the length (in
+ * {@code char}s) of the text range is
+ * {@code endIndex-beginIndex}. Unpaired surrogates within
* this sequence count as one code point each.
*
- * @param beginIndex the index to the first <code>char</code> of
+ * @param beginIndex the index to the first {@code char} of
* the text range.
- * @param endIndex the index after the last <code>char</code> of
+ * @param endIndex the index after the last {@code char} of
* the text range.
* @return the number of Unicode code points in the specified text
* range
* @exception IndexOutOfBoundsException if the
- * <code>beginIndex</code> is negative, or <code>endIndex</code>
+ * {@code beginIndex} is negative, or {@code endIndex}
* is larger than the length of this sequence, or
- * <code>beginIndex</code> is larger than <code>endIndex</code>.
+ * {@code beginIndex} is larger than {@code endIndex}.
*/
public int codePointCount(int beginIndex, int endIndex) {
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -290,22 +298,22 @@
/**
* Returns the index within this sequence that is offset from the
- * given <code>index</code> by <code>codePointOffset</code> code
+ * given {@code index} by {@code codePointOffset} code
* points. Unpaired surrogates within the text range given by
- * <code>index</code> and <code>codePointOffset</code> count as
+ * {@code index} and {@code codePointOffset} count as
* one code point each.
*
* @param index the index to be offset
* @param codePointOffset the offset in code points
* @return the index within this sequence
- * @exception IndexOutOfBoundsException if <code>index</code>
+ * @exception IndexOutOfBoundsException if {@code index}
* is negative or larger then the length of this sequence,
- * or if <code>codePointOffset</code> is positive and the subsequence
- * starting with <code>index</code> has fewer than
- * <code>codePointOffset</code> code points,
- * or if <code>codePointOffset</code> is negative and the subsequence
- * before <code>index</code> has fewer than the absolute value of
- * <code>codePointOffset</code> code points.
+ * or if {@code codePointOffset} is positive and the subsequence
+ * starting with {@code index} has fewer than
+ * {@code codePointOffset} code points,
+ * or if {@code codePointOffset} is negative and the subsequence
+ * before {@code index} has fewer than the absolute value of
+ * {@code codePointOffset} code points.
*/
public int offsetByCodePoints(int index, int codePointOffset) {
if (index < 0 || index > count) {
@@ -317,32 +325,30 @@
/**
* Characters are copied from this sequence into the
- * destination character array <code>dst</code>. The first character to
- * be copied is at index <code>srcBegin</code>; the last character to
- * be copied is at index <code>srcEnd-1</code>. The total number of
- * characters to be copied is <code>srcEnd-srcBegin</code>. The
- * characters are copied into the subarray of <code>dst</code> starting
- * at index <code>dstBegin</code> and ending at index:
- * <p><blockquote><pre>
+ * destination character array {@code dst}. The first character to
+ * be copied is at index {@code srcBegin}; the last character to
+ * be copied is at index {@code srcEnd-1}. The total number of
+ * characters to be copied is {@code srcEnd-srcBegin}. The
+ * characters are copied into the subarray of {@code dst} starting
+ * at index {@code dstBegin} and ending at index:
+ * <pre>{@code
* dstbegin + (srcEnd-srcBegin) - 1
- * </pre></blockquote>
+ * }</pre>
*
* @param srcBegin start copying at this offset.
* @param srcEnd stop copying at this offset.
* @param dst the array to copy the data into.
- * @param dstBegin offset into <code>dst</code>.
- * @throws NullPointerException if <code>dst</code> is
- * <code>null</code>.
+ * @param dstBegin offset into {@code dst}.
* @throws IndexOutOfBoundsException if any of the following is true:
* <ul>
- * <li><code>srcBegin</code> is negative
- * <li><code>dstBegin</code> is negative
- * <li>the <code>srcBegin</code> argument is greater than
- * the <code>srcEnd</code> argument.
- * <li><code>srcEnd</code> is greater than
- * <code>this.length()</code>.
- * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
- * <code>dst.length</code>
+ * <li>{@code srcBegin} is negative
+ * <li>{@code dstBegin} is negative
+ * <li>the {@code srcBegin} argument is greater than
+ * the {@code srcEnd} argument.
+ * <li>{@code srcEnd} is greater than
+ * {@code this.length()}.
+ * <li>{@code dstBegin+srcEnd-srcBegin} is greater than
+ * {@code dst.length}
* </ul>
*/
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
@@ -357,18 +363,18 @@
}
/**
- * The character at the specified index is set to <code>ch</code>. This
+ * The character at the specified index is set to {@code ch}. This
* sequence is altered to represent a new character sequence that is
* identical to the old character sequence, except that it contains the
- * character <code>ch</code> at position <code>index</code>.
+ * character {@code ch} at position {@code index}.
* <p>
* The index argument must be greater than or equal to
- * <code>0</code>, and less than the length of this sequence.
+ * {@code 0}, and less than the length of this sequence.
*
* @param index the index of the character to modify.
* @param ch the new character.
- * @throws IndexOutOfBoundsException if <code>index</code> is
- * negative or greater than or equal to <code>length()</code>.
+ * @throws IndexOutOfBoundsException if {@code index} is
+ * negative or greater than or equal to {@code length()}.
*/
public void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
@@ -412,10 +418,11 @@
* @hide
*/
public AbstractStringBuilder append(String str) {
- if (str == null) str = "null";
+ if (str == null)
+ return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
- str.getCharsNoCheck(0, len, value, count);
+ str.getChars(0, len, value, count);
count += len;
return this;
}
@@ -424,7 +431,7 @@
/** @hide */
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
- return append("null");
+ return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
@@ -432,18 +439,46 @@
return this;
}
+ /**
+ * @since 1.8
+ * @hide
+ */
+ AbstractStringBuilder append(AbstractStringBuilder asb) {
+ if (asb == null)
+ return appendNull();
+ int len = asb.length();
+ ensureCapacityInternal(count + len);
+ asb.getChars(0, len, value, count);
+ count += len;
+ return this;
+ }
+
// Documentation in subclasses because of synchro difference
/** @hide */
+ @Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
- s = "null";
+ return appendNull();
if (s instanceof String)
return this.append((String)s);
- if (s instanceof StringBuffer)
- return this.append((StringBuffer)s);
+ if (s instanceof AbstractStringBuilder)
+ return this.append((AbstractStringBuilder)s);
+
return this.append(s, 0, s.length());
}
+ private AbstractStringBuilder appendNull() {
+ int c = count;
+ ensureCapacityInternal(c + 4);
+ final char[] value = this.value;
+ value[c++] = 'n';
+ value[c++] = 'u';
+ value[c++] = 'l';
+ value[c++] = 'l';
+ count = c;
+ return this;
+ }
+
/**
* Appends a subsequence of the specified {@code CharSequence} to this
* sequence.
@@ -474,6 +509,7 @@
* {@code end} is greater than {@code s.length()}
* @hide
*/
+ @Override
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
@@ -483,16 +519,8 @@
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
- if (s instanceof String) {
- ((String) s).getCharsNoCheck(start, end, value, count);
- } else if (s instanceof AbstractStringBuilder) {
- AbstractStringBuilder other = (AbstractStringBuilder) s;
- System.arraycopy(other.value, start, value, count, len);
- } else {
- for (int i = start, j = count; i < end; i++, j++) {
- value[j] = s.charAt(i);
- }
- }
+ for (int i = start, j = count; i < end; i++, j++)
+ value[j] = s.charAt(i);
count += len;
return this;
}
@@ -569,19 +597,17 @@
public AbstractStringBuilder append(boolean b) {
if (b) {
ensureCapacityInternal(count + 4);
- value[count] = 't';
- value[count+1] = 'r';
- value[count+2] = 'u';
- value[count+3] = 'e';
- count += 4;
+ value[count++] = 't';
+ value[count++] = 'r';
+ value[count++] = 'u';
+ value[count++] = 'e';
} else {
ensureCapacityInternal(count + 5);
- value[count] = 'f';
- value[count+1] = 'a';
- value[count+2] = 'l';
- value[count+3] = 's';
- value[count+4] = 'e';
- count += 5;
+ value[count++] = 'f';
+ value[count++] = 'a';
+ value[count++] = 'l';
+ value[count++] = 's';
+ value[count++] = 'e';
}
return this;
}
@@ -602,6 +628,7 @@
* @return a reference to this object.
* @hide
*/
+ @Override
public AbstractStringBuilder append(char c) {
ensureCapacityInternal(count + 1);
value[count++] = c;
@@ -676,9 +703,7 @@
* @hide
*/
public AbstractStringBuilder append(float f) {
- FloatingDecimal.getThreadLocalInstance()
- .loadFloat(f)
- .appendTo(this);
+ FloatingDecimal.appendTo(f,this);
return this;
}
@@ -696,9 +721,7 @@
* @hide
*/
public AbstractStringBuilder append(double d) {
- FloatingDecimal.getThreadLocalInstance()
- .loadDouble(d)
- .appendTo(this);
+ FloatingDecimal.appendTo(d,this);
return this;
}
@@ -770,21 +793,21 @@
}
/**
- * Removes the <code>char</code> at the specified position in this
- * sequence. This sequence is shortened by one <code>char</code>.
+ * Removes the {@code char} at the specified position in this
+ * sequence. This sequence is shortened by one {@code char}.
*
* <p>Note: If the character at the given index is a supplementary
* character, this method does not remove the entire character. If
* correct handling of supplementary characters is required,
- * determine the number of <code>char</code>s to remove by calling
- * <code>Character.charCount(thisSequence.codePointAt(index))</code>,
- * where <code>thisSequence</code> is this sequence.
+ * determine the number of {@code char}s to remove by calling
+ * {@code Character.charCount(thisSequence.codePointAt(index))},
+ * where {@code thisSequence} is this sequence.
*
- * @param index Index of <code>char</code> to remove
+ * @param index Index of {@code char} to remove
* @return This object.
- * @throws StringIndexOutOfBoundsException if the <code>index</code>
+ * @throws StringIndexOutOfBoundsException if the {@code index}
* is negative or greater than or equal to
- * <code>length()</code>.
+ * {@code length()}.
* @hide
*/
public AbstractStringBuilder deleteCharAt(int index) {
@@ -797,12 +820,12 @@
/**
* Replaces the characters in a substring of this sequence
- * with characters in the specified <code>String</code>. The substring
- * begins at the specified <code>start</code> and extends to the character
- * at index <code>end - 1</code> or to the end of the
+ * with characters in the specified {@code String}. The substring
+ * begins at the specified {@code start} and extends to the character
+ * at index {@code end - 1} or to the end of the
* sequence if no such character exists. First the
* characters in the substring are removed and then the specified
- * <code>String</code> is inserted at <code>start</code>. (This
+ * {@code String} is inserted at {@code start}. (This
* sequence will be lengthened to accommodate the
* specified String if necessary.)
*
@@ -810,9 +833,9 @@
* @param end The ending index, exclusive.
* @param str String that will replace previous contents.
* @return This object.
- * @throws StringIndexOutOfBoundsException if <code>start</code>
- * is negative, greater than <code>length()</code>, or
- * greater than <code>end</code>.
+ * @throws StringIndexOutOfBoundsException if {@code start}
+ * is negative, greater than {@code length()}, or
+ * greater than {@code end}.
* @hide
*/
public AbstractStringBuilder replace(int start, int end, String str) {
@@ -830,20 +853,20 @@
ensureCapacityInternal(newCount);
System.arraycopy(value, end, value, start + len, count - end);
- str.getCharsNoCheck(0, len, value, start);
+ str.getChars(value, start);
count = newCount;
return this;
}
/**
- * Returns a new <code>String</code> that contains a subsequence of
+ * Returns a new {@code String} that contains a subsequence of
* characters currently contained in this character sequence. The
* substring begins at the specified index and extends to the end of
* this sequence.
*
* @param start The beginning index, inclusive.
* @return The new string.
- * @throws StringIndexOutOfBoundsException if <code>start</code> is
+ * @throws StringIndexOutOfBoundsException if {@code start} is
* less than zero, or greater than the length of this object.
*/
public String substring(int start) {
@@ -855,44 +878,45 @@
*
* <p> An invocation of this method of the form
*
- * <blockquote><pre>
- * sb.subSequence(begin, end)</pre></blockquote>
+ * <pre>{@code
+ * sb.subSequence(begin, end)}</pre>
*
* behaves in exactly the same way as the invocation
*
- * <blockquote><pre>
- * sb.substring(begin, end)</pre></blockquote>
+ * <pre>{@code
+ * sb.substring(begin, end)}</pre>
*
* This method is provided so that this class can
- * implement the {@link CharSequence} interface. </p>
+ * implement the {@link CharSequence} interface.
*
* @param start the start index, inclusive.
* @param end the end index, exclusive.
* @return the specified subsequence.
*
* @throws IndexOutOfBoundsException
- * if <tt>start</tt> or <tt>end</tt> are negative,
- * if <tt>end</tt> is greater than <tt>length()</tt>,
- * or if <tt>start</tt> is greater than <tt>end</tt>
+ * if {@code start} or {@code end} are negative,
+ * if {@code end} is greater than {@code length()},
+ * or if {@code start} is greater than {@code end}
* @spec JSR-51
*/
+ @Override
public CharSequence subSequence(int start, int end) {
return substring(start, end);
}
/**
- * Returns a new <code>String</code> that contains a subsequence of
+ * Returns a new {@code String} that contains a subsequence of
* characters currently contained in this sequence. The
- * substring begins at the specified <code>start</code> and
- * extends to the character at index <code>end - 1</code>.
+ * substring begins at the specified {@code start} and
+ * extends to the character at index {@code end - 1}.
*
* @param start The beginning index, inclusive.
* @param end The ending index, exclusive.
* @return The new string.
- * @throws StringIndexOutOfBoundsException if <code>start</code>
- * or <code>end</code> are negative or greater than
- * <code>length()</code>, or <code>start</code> is
- * greater than <code>end</code>.
+ * @throws StringIndexOutOfBoundsException if {@code start}
+ * or {@code end} are negative or greater than
+ * {@code length()}, or {@code start} is
+ * greater than {@code end}.
*/
public String substring(int start, int end) {
if (start < 0)
@@ -1006,7 +1030,7 @@
int len = str.length();
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
- str.getCharsNoCheck(0, len, value, offset);
+ str.getChars(value, offset);
count += len;
return this;
}
@@ -1294,18 +1318,16 @@
* Returns the index within this string of the first occurrence of the
* specified substring. The integer returned is the smallest value
* <i>k</i> such that:
- * <blockquote><pre>
+ * <pre>{@code
* this.toString().startsWith(str, <i>k</i>)
- * </pre></blockquote>
- * is <code>true</code>.
+ * }</pre>
+ * is {@code true}.
*
* @param str any string.
* @return if the string argument occurs as a substring within this
* object, then the index of the first character of the first
* such substring is returned; if it does not occur as a
- * substring, <code>-1</code> is returned.
- * @throws java.lang.NullPointerException if <code>str</code> is
- * <code>null</code>.
+ * substring, {@code -1} is returned.
*/
public int indexOf(String str) {
return indexOf(str, 0);
@@ -1314,19 +1336,17 @@
/**
* Returns the index within this string of the first occurrence of the
* specified substring, starting at the specified index. The integer
- * returned is the smallest value <tt>k</tt> for which:
- * <blockquote><pre>
- * k >= Math.min(fromIndex, str.length()) &&
+ * returned is the smallest value {@code k} for which:
+ * <pre>{@code
+ * k >= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* If no such value of <i>k</i> exists, then -1 is returned.
*
* @param str the substring for which to search.
* @param fromIndex the index from which to start the search.
* @return the index within this string of the first occurrence of the
* specified substring, starting at the specified index.
- * @throws java.lang.NullPointerException if <code>str</code> is
- * <code>null</code>.
*/
public int indexOf(String str, int fromIndex) {
return String.indexOf(value, 0, count,
@@ -1336,20 +1356,18 @@
/**
* Returns the index within this string of the rightmost occurrence
* of the specified substring. The rightmost empty string "" is
- * considered to occur at the index value <code>this.length()</code>.
+ * considered to occur at the index value {@code this.length()}.
* The returned index is the largest value <i>k</i> such that
- * <blockquote><pre>
+ * <pre>{@code
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* is true.
*
* @param str the substring to search for.
* @return if the string argument occurs one or more times as a substring
* within this object, then the index of the first character of
* the last such substring is returned. If it does not occur as
- * a substring, <code>-1</code> is returned.
- * @throws java.lang.NullPointerException if <code>str</code> is
- * <code>null</code>.
+ * a substring, {@code -1} is returned.
*/
public int lastIndexOf(String str) {
return lastIndexOf(str, count);
@@ -1359,22 +1377,20 @@
* Returns the index within this string of the last occurrence of the
* specified substring. The integer returned is the largest value <i>k</i>
* such that:
- * <blockquote><pre>
- * k <= Math.min(fromIndex, str.length()) &&
+ * <pre>{@code
+ * k <= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* If no such value of <i>k</i> exists, then -1 is returned.
*
* @param str the substring to search for.
* @param fromIndex the index to start the search from.
* @return the index within this sequence of the last occurrence of the
* specified substring.
- * @throws java.lang.NullPointerException if <code>str</code> is
- * <code>null</code>.
*/
public int lastIndexOf(String str, int fromIndex) {
return String.lastIndexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ str.toCharArray(), 0, str.length(), fromIndex);
}
/**
@@ -1385,8 +1401,8 @@
* is never reversed.
*
* Let <i>n</i> be the character length of this character sequence
- * (not the length in <code>char</code> values) just prior to
- * execution of the <code>reverse</code> method. Then the
+ * (not the length in {@code char} values) just prior to
+ * execution of the {@code reverse} method. Then the
* character at index <i>k</i> in the new character sequence is
* equal to the character at index <i>n-k-1</i> in the old
* character sequence.
@@ -1394,56 +1410,61 @@
* <p>Note that the reverse operation may result in producing
* surrogate pairs that were unpaired low-surrogates and
* high-surrogates before the operation. For example, reversing
- * "\uDC00\uD800" produces "\uD800\uDC00" which is
+ * "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
* a valid surrogate pair.
*
* @return a reference to this object.
* @hide
*/
public AbstractStringBuilder reverse() {
- boolean hasSurrogate = false;
+ boolean hasSurrogates = false;
int n = count - 1;
- for (int j = (n-1) >> 1; j >= 0; --j) {
- char temp = value[j];
- char temp2 = value[n - j];
- if (!hasSurrogate) {
- hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
- || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
+ for (int j = (n-1) >> 1; j >= 0; j--) {
+ int k = n - j;
+ char cj = value[j];
+ char ck = value[k];
+ value[j] = ck;
+ value[k] = cj;
+ if (Character.isSurrogate(cj) ||
+ Character.isSurrogate(ck)) {
+ hasSurrogates = true;
}
- value[j] = temp2;
- value[n - j] = temp;
}
- if (hasSurrogate) {
- // Reverse back all valid surrogate pairs
- for (int i = 0; i < count - 1; i++) {
- char c2 = value[i];
- if (Character.isLowSurrogate(c2)) {
- char c1 = value[i + 1];
- if (Character.isHighSurrogate(c1)) {
- value[i++] = c1;
- value[i] = c2;
- }
- }
- }
+ if (hasSurrogates) {
+ reverseAllValidSurrogatePairs();
}
return this;
}
+ /** Outlined helper method for reverse() */
+ private void reverseAllValidSurrogatePairs() {
+ for (int i = 0; i < count - 1; i++) {
+ char c2 = value[i];
+ if (Character.isLowSurrogate(c2)) {
+ char c1 = value[i + 1];
+ if (Character.isHighSurrogate(c1)) {
+ value[i++] = c1;
+ value[i] = c2;
+ }
+ }
+ }
+ }
+
/**
* Returns a string representing the data in this sequence.
- * A new <code>String</code> object is allocated and initialized to
+ * A new {@code String} object is allocated and initialized to
* contain the character sequence currently represented by this
- * object. This <code>String</code> is then returned. Subsequent
+ * object. This {@code String} is then returned. Subsequent
* changes to this sequence do not affect the contents of the
- * <code>String</code>.
+ * {@code String}.
*
* @return a string representation of this sequence of characters.
- * @hide
*/
+ @Override
public abstract String toString();
/**
- * Needed by <tt>String</tt> for the contentEquals method.
+ * Needed by {@code String} for the contentEquals method.
*/
final char[] getValue() {
return value;
diff --git a/ojluni/src/main/java/java/lang/ClassCastException.java b/ojluni/src/main/java/java/lang/ClassCastException.java
old mode 100755
new mode 100644
index fc9b261..e4ca76c
--- a/ojluni/src/main/java/java/lang/ClassCastException.java
+++ b/ojluni/src/main/java/java/lang/ClassCastException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* Thrown to indicate that the code has attempted to cast an object
* to a subclass of which it is not an instance. For example, the
* following code generates a <code>ClassCastException</code>:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* Object x = new Integer(0);
* System.out.println((String)x);
* </pre></blockquote>
diff --git a/ojluni/src/main/java/java/lang/Comparable.java b/ojluni/src/main/java/java/lang/Comparable.java
old mode 100755
new mode 100644
index c049323..c14e493
--- a/ojluni/src/main/java/java/lang/Comparable.java
+++ b/ojluni/src/main/java/java/lang/Comparable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
* method.<p>
*
* For example, if one adds two keys <tt>a</tt> and <tt>b</tt> such that
- * <tt>(!a.equals(b) && a.compareTo(b) == 0)</tt> to a sorted
+ * {@code (!a.equals(b) && a.compareTo(b) == 0)} to a sorted
* set that does not use an explicit comparator, the second <tt>add</tt>
* operation returns false (and the size of the sorted set does not increase)
* because <tt>a</tt> and <tt>b</tt> are equivalent from the sorted set's
@@ -93,7 +93,6 @@
* @see java.util.Comparator
* @since 1.2
*/
-
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
diff --git a/ojluni/src/main/java/java/lang/Deprecated.java b/ojluni/src/main/java/java/lang/Deprecated.java
old mode 100755
new mode 100644
index 2b1546b..58a0691
--- a/ojluni/src/main/java/java/lang/Deprecated.java
+++ b/ojluni/src/main/java/java/lang/Deprecated.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
*
* @author Neal Gafter
* @since 1.5
+ * @jls 9.6.3.6 @Deprecated
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
diff --git a/ojluni/src/main/java/java/lang/Double.java b/ojluni/src/main/java/java/lang/Double.java
old mode 100755
new mode 100644
index 59f8088..2bc2bf3
--- a/ojluni/src/main/java/java/lang/Double.java
+++ b/ojluni/src/main/java/java/lang/Double.java
@@ -26,6 +26,7 @@
package java.lang;
+import sun.misc.FloatingDecimal;
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;
@@ -135,6 +136,7 @@
*
* @since JDK1.1
*/
+ @SuppressWarnings("unchecked")
public static final Class<Double> TYPE = (Class<Double>) double[].class.getComponentType();
/**
@@ -146,7 +148,7 @@
* <li>Otherwise, the result is a string that represents the sign and
* magnitude (absolute value) of the argument. If the sign is negative,
* the first character of the result is '{@code -}'
- * (<code>'\u002D'</code>); if the sign is positive, no sign character
+ * ({@code '\u005Cu002D'}); if the sign is positive, no sign character
* appears in the result. As for the magnitude <i>m</i>:
* <ul>
* <li>If <i>m</i> is infinity, it is represented by the characters
@@ -162,7 +164,7 @@
* <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less
* than 10<sup>7</sup>, then it is represented as the integer part of
* <i>m</i>, in decimal form with no leading zeroes, followed by
- * '{@code .}' (<code>'\u002E'</code>), followed by one or
+ * '{@code .}' ({@code '\u005Cu002E'}), followed by one or
* more decimal digits representing the fractional part of <i>m</i>.
*
* <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or
@@ -174,9 +176,9 @@
* 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10. The
* magnitude is then represented as the integer part of <i>a</i>,
* as a single decimal digit, followed by '{@code .}'
- * (<code>'\u002E'</code>), followed by decimal digits
+ * ({@code '\u005Cu002E'}), followed by decimal digits
* representing the fractional part of <i>a</i>, followed by the
- * letter '{@code E}' (<code>'\u0045'</code>), followed
+ * letter '{@code E}' ({@code '\u005Cu0045'}), followed
* by a representation of <i>n</i> as a decimal integer, as
* produced by the method {@link Integer#toString(int)}.
* </ul>
@@ -200,7 +202,7 @@
* @return a string representation of the argument.
*/
public static String toString(double d) {
- return FloatingDecimal.getThreadLocalInstance().loadDouble(d).toJavaFormatString();
+ return FloatingDecimal.toJavaFormatString(d);
}
/**
@@ -214,7 +216,7 @@
* <li>Otherwise, the result is a string that represents the sign
* and magnitude of the argument. If the sign is negative, the
* first character of the result is '{@code -}'
- * (<code>'\u002D'</code>); if the sign is positive, no sign
+ * ({@code '\u005Cu002D'}); if the sign is positive, no sign
* character appears in the result. As for the magnitude <i>m</i>:
*
* <ul>
@@ -255,7 +257,7 @@
* </ul>
*
* <table border>
- * <caption><h3>Examples</h3></caption>
+ * <caption>Examples</caption>
* <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
* <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
* <tr><td>{@code -1.0}</td> <td>{@code -0x1.0p0}</td>
@@ -283,14 +285,14 @@
* 7.19.6.1; however, the output of this method is more
* tightly specified.
*/
- if (!FpUtils.isFinite(d) )
+ if (!isFinite(d) )
// For infinity and NaN, use the decimal output.
return Double.toString(d);
else {
// Initialized to maximum size of output.
- StringBuffer answer = new StringBuffer(24);
+ StringBuilder answer = new StringBuilder(24);
- if (FpUtils.rawCopySign(1.0, d) == -1.0) // value is negative,
+ if (Math.copySign(1.0, d) == -1.0) // value is negative,
answer.append("-"); // so append sign info
answer.append("0x");
@@ -299,8 +301,7 @@
if(d == 0.0) {
answer.append("0.0p0");
- }
- else {
+ } else {
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
// Isolate significand bits and OR in a high-order bit
@@ -323,13 +324,14 @@
"0":
signif.replaceFirst("0{1,12}$", ""));
+ answer.append('p');
// If the value is subnormal, use the E_min exponent
// value for double; otherwise, extract and report d's
// exponent (the representation of a subnormal uses
// E_min -1).
- answer.append("p" + (subnormal ?
- DoubleConsts.MIN_EXPONENT:
- FpUtils.getExponent(d) ));
+ answer.append(subnormal ?
+ DoubleConsts.MIN_EXPONENT:
+ Math.getExponent(d));
}
return answer.toString();
}
@@ -360,15 +362,11 @@
* <dd><i>SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexFloatingPointLiteral</i>:
* <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexSignificand:</i>
* <dd><i>HexNumeral</i>
@@ -379,15 +377,11 @@
* </i>{@code .} <i>HexDigits</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponent:</i>
* <dd><i>BinaryExponentIndicator SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponentIndicator:</i>
* <dd>{@code p}
@@ -452,8 +446,7 @@
* a {@code NumberFormatException} be thrown, the regular
* expression below can be used to screen the input string:
*
- * <code>
- * <pre>
+ * <pre>{@code
* final String Digits = "(\\p{Digit}+)";
* final String HexDigits = "(\\p{XDigit}+)";
* // an exponent is 'e' or 'E' followed by an optionally
@@ -473,7 +466,7 @@
* // in addition to strings of floating-point literals, the
* // two sub-patterns below are simplifications of the grammar
* // productions from section 3.10.2 of
- * // <cite>The Java™ Language Specification</cite>.
+ * // The Java Language Specification.
*
* // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
* "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
@@ -498,8 +491,7 @@
* else {
* // Perform suitable alternative action
* }
- * </pre>
- * </code>
+ * }</pre>
*
* @param s the string to be parsed.
* @return a {@code Double} object holding the value
@@ -508,7 +500,7 @@
* parsable number.
*/
public static Double valueOf(String s) throws NumberFormatException {
- return new Double(FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).doubleValue());
+ return new Double(parseDouble(s));
}
/**
@@ -544,7 +536,7 @@
* @since 1.2
*/
public static double parseDouble(String s) throws NumberFormatException {
- return FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).doubleValue();
+ return FloatingDecimal.parseDouble(s);
}
/**
@@ -555,7 +547,7 @@
* @return {@code true} if the value of the argument is NaN;
* {@code false} otherwise.
*/
- static public boolean isNaN(double v) {
+ public static boolean isNaN(double v) {
return (v != v);
}
@@ -567,7 +559,7 @@
* @return {@code true} if the value of the argument is positive
* infinity or negative infinity; {@code false} otherwise.
*/
- static public boolean isInfinite(double v) {
+ public static boolean isInfinite(double v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
@@ -614,8 +606,7 @@
* @see java.lang.Double#valueOf(java.lang.String)
*/
public Double(String s) throws NumberFormatException {
- // REMIND: this is inefficient
- this(valueOf(s).doubleValue());
+ value = parseDouble(s);
}
/**
@@ -655,11 +646,12 @@
}
/**
- * Returns the value of this {@code Double} as a {@code byte} (by
- * casting to a {@code byte}).
+ * Returns the value of this {@code Double} as a {@code byte}
+ * after a narrowing primitive conversion.
*
* @return the {@code double} value represented by this object
* converted to type {@code byte}
+ * @jls 5.1.3 Narrowing Primitive Conversions
* @since JDK1.1
*/
public byte byteValue() {
@@ -667,11 +659,12 @@
}
/**
- * Returns the value of this {@code Double} as a
- * {@code short} (by casting to a {@code short}).
+ * Returns the value of this {@code Double} as a {@code short}
+ * after a narrowing primitive conversion.
*
* @return the {@code double} value represented by this object
* converted to type {@code short}
+ * @jls 5.1.3 Narrowing Primitive Conversions
* @since JDK1.1
*/
public short shortValue() {
@@ -679,8 +672,9 @@
}
/**
- * Returns the value of this {@code Double} as an
- * {@code int} (by casting to type {@code int}).
+ * Returns the value of this {@code Double} as an {@code int}
+ * after a narrowing primitive conversion.
+ * @jls 5.1.3 Narrowing Primitive Conversions
*
* @return the {@code double} value represented by this object
* converted to type {@code int}
@@ -690,22 +684,24 @@
}
/**
- * Returns the value of this {@code Double} as a
- * {@code long} (by casting to type {@code long}).
+ * Returns the value of this {@code Double} as a {@code long}
+ * after a narrowing primitive conversion.
*
* @return the {@code double} value represented by this object
* converted to type {@code long}
+ * @jls 5.1.3 Narrowing Primitive Conversions
*/
public long longValue() {
return (long)value;
}
/**
- * Returns the {@code float} value of this
- * {@code Double} object.
+ * Returns the value of this {@code Double} as a {@code float}
+ * after a narrowing primitive conversion.
*
* @return the {@code double} value represented by this object
* converted to type {@code float}
+ * @jls 5.1.3 Narrowing Primitive Conversions
* @since JDK1.0
*/
public float floatValue() {
@@ -713,13 +709,12 @@
}
/**
- * Returns the {@code double} value of this
- * {@code Double} object.
+ * Returns the {@code double} value of this {@code Double} object.
*
* @return the {@code double} value represented by this object
*/
public double doubleValue() {
- return (double)value;
+ return value;
}
/**
@@ -743,6 +738,7 @@
*
* @return a {@code hash code} value for this object.
*/
+ @Override
public int hashCode() {
return Double.hashCode(value);
}
@@ -912,13 +908,13 @@
* <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three
* values that can be computed from the argument:
*
- * <blockquote><pre>
- * int s = ((bits >> 63) == 0) ? 1 : -1;
- * int e = (int)((bits >> 52) & 0x7ffL);
+ * <blockquote><pre>{@code
+ * int s = ((bits >> 63) == 0) ? 1 : -1;
+ * int e = (int)((bits >> 52) & 0x7ffL);
* long m = (e == 0) ?
- * (bits & 0xfffffffffffffL) << 1 :
+ * (bits & 0xfffffffffffffL) << 1 :
* (bits & 0xfffffffffffffL) | 0x10000000000000L;
- * </pre></blockquote>
+ * }</pre></blockquote>
*
* Then the floating-point result equals the value of the mathematical
* expression <i>s</i>·<i>m</i>·2<sup><i>e</i>-1075</sup>.
diff --git a/ojluni/src/main/java/java/lang/Float.java b/ojluni/src/main/java/java/lang/Float.java
old mode 100755
new mode 100644
index d75953e..32bd625
--- a/ojluni/src/main/java/java/lang/Float.java
+++ b/ojluni/src/main/java/java/lang/Float.java
@@ -26,7 +26,7 @@
package java.lang;
-import sun.misc.FpUtils;
+import sun.misc.FloatingDecimal;
import sun.misc.FloatConsts;
import sun.misc.DoubleConsts;
@@ -134,6 +134,7 @@
*
* @since JDK1.1
*/
+ @SuppressWarnings("unchecked")
public static final Class<Float> TYPE = (Class<Float>) float[].class.getComponentType();
/**
@@ -145,7 +146,7 @@
* <li>Otherwise, the result is a string that represents the sign and
* magnitude (absolute value) of the argument. If the sign is
* negative, the first character of the result is
- * '{@code -}' (<code>'\u002D'</code>); if the sign is
+ * '{@code -}' ({@code '\u005Cu002D'}); if the sign is
* positive, no sign character appears in the result. As for
* the magnitude <i>m</i>:
* <ul>
@@ -161,7 +162,7 @@
* less than 10<sup>7</sup>, then it is represented as the
* integer part of <i>m</i>, in decimal form with no leading
* zeroes, followed by '{@code .}'
- * (<code>'\u002E'</code>), followed by one or more
+ * ({@code '\u005Cu002E'}), followed by one or more
* decimal digits representing the fractional part of
* <i>m</i>.
* <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
@@ -173,10 +174,10 @@
* 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10.
* The magnitude is then represented as the integer part of
* <i>a</i>, as a single decimal digit, followed by
- * '{@code .}' (<code>'\u002E'</code>), followed by
+ * '{@code .}' ({@code '\u005Cu002E'}), followed by
* decimal digits representing the fractional part of
* <i>a</i>, followed by the letter '{@code E}'
- * (<code>'\u0045'</code>), followed by a representation
+ * ({@code '\u005Cu0045'}), followed by a representation
* of <i>n</i> as a decimal integer, as produced by the
* method {@link java.lang.Integer#toString(int)}.
*
@@ -203,7 +204,7 @@
* @return a string representation of the argument.
*/
public static String toString(float f) {
- return FloatingDecimal.getThreadLocalInstance().loadFloat(f).toJavaFormatString();
+ return FloatingDecimal.toJavaFormatString(f);
}
/**
@@ -217,7 +218,7 @@
* <li>Otherwise, the result is a string that represents the sign and
* magnitude (absolute value) of the argument. If the sign is negative,
* the first character of the result is '{@code -}'
- * (<code>'\u002D'</code>); if the sign is positive, no sign character
+ * ({@code '\u005Cu002D'}); if the sign is positive, no sign character
* appears in the result. As for the magnitude <i>m</i>:
*
* <ul>
@@ -258,7 +259,7 @@
* </ul>
*
* <table border>
- * <caption><h3>Examples</h3></caption>
+ * <caption>Examples</caption>
* <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
* <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
* <tr><td>{@code -1.0}</td> <td>{@code -0x1.0p0}</td>
@@ -286,10 +287,10 @@
// Adjust exponent to create subnormal double, then
// replace subnormal double exponent with subnormal float
// exponent
- String s = Double.toHexString(FpUtils.scalb((double)f,
- /* -1022+126 */
- DoubleConsts.MIN_EXPONENT-
- FloatConsts.MIN_EXPONENT));
+ String s = Double.toHexString(Math.scalb((double)f,
+ /* -1022+126 */
+ DoubleConsts.MIN_EXPONENT-
+ FloatConsts.MIN_EXPONENT));
return s.replaceFirst("p-1022$", "p-126");
}
else // double string will be the same as float string
@@ -321,15 +322,11 @@
* <dd><i>SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexFloatingPointLiteral</i>:
* <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexSignificand:</i>
* <dd><i>HexNumeral</i>
@@ -340,15 +337,11 @@
* </i>{@code .} <i>HexDigits</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponent:</i>
* <dd><i>BinaryExponentIndicator SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponentIndicator:</i>
* <dd>{@code p}
@@ -421,7 +414,7 @@
* parsable number.
*/
public static Float valueOf(String s) throws NumberFormatException {
- return new Float(FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).floatValue());
+ return new Float(parseFloat(s));
}
/**
@@ -456,7 +449,7 @@
* @since 1.2
*/
public static float parseFloat(String s) throws NumberFormatException {
- return FloatingDecimal.getThreadLocalInstance().readJavaFormatString(s).floatValue();
+ return FloatingDecimal.parseFloat(s);
}
/**
@@ -467,7 +460,7 @@
* @return {@code true} if the argument is NaN;
* {@code false} otherwise.
*/
- static public boolean isNaN(float v) {
+ public static boolean isNaN(float v) {
return (v != v);
}
@@ -479,10 +472,11 @@
* @return {@code true} if the argument is positive infinity or
* negative infinity; {@code false} otherwise.
*/
- static public boolean isInfinite(float v) {
+ public static boolean isInfinite(float v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
+
/**
* Returns {@code true} if the argument is a finite floating-point
* value; returns {@code false} otherwise (for NaN and infinity
@@ -536,8 +530,7 @@
* @see java.lang.Float#valueOf(java.lang.String)
*/
public Float(String s) throws NumberFormatException {
- // REMIND: this is inefficient
- this(valueOf(s).floatValue());
+ value = parseFloat(s);
}
/**
@@ -577,22 +570,24 @@
}
/**
- * Returns the value of this {@code Float} as a {@code byte} (by
- * casting to a {@code byte}).
+ * Returns the value of this {@code Float} as a {@code byte} after
+ * a narrowing primitive conversion.
*
* @return the {@code float} value represented by this object
* converted to type {@code byte}
+ * @jls 5.1.3 Narrowing Primitive Conversions
*/
public byte byteValue() {
return (byte)value;
}
/**
- * Returns the value of this {@code Float} as a {@code short} (by
- * casting to a {@code short}).
+ * Returns the value of this {@code Float} as a {@code short}
+ * after a narrowing primitive conversion.
*
* @return the {@code float} value represented by this object
* converted to type {@code short}
+ * @jls 5.1.3 Narrowing Primitive Conversions
* @since JDK1.1
*/
public short shortValue() {
@@ -600,22 +595,24 @@
}
/**
- * Returns the value of this {@code Float} as an {@code int} (by
- * casting to type {@code int}).
+ * Returns the value of this {@code Float} as an {@code int} after
+ * a narrowing primitive conversion.
*
* @return the {@code float} value represented by this object
* converted to type {@code int}
+ * @jls 5.1.3 Narrowing Primitive Conversions
*/
public int intValue() {
return (int)value;
}
/**
- * Returns value of this {@code Float} as a {@code long} (by
- * casting to type {@code long}).
+ * Returns value of this {@code Float} as a {@code long} after a
+ * narrowing primitive conversion.
*
* @return the {@code float} value represented by this object
* converted to type {@code long}
+ * @jls 5.1.3 Narrowing Primitive Conversions
*/
public long longValue() {
return (long)value;
@@ -631,11 +628,12 @@
}
/**
- * Returns the {@code double} value of this {@code Float} object.
+ * Returns the value of this {@code Float} as a {@code double}
+ * after a widening primitive conversion.
*
* @return the {@code float} value represented by this
- * object is converted to type {@code double} and the
- * result of the conversion is returned.
+ * object converted to type {@code double}
+ * @jls 5.1.2 Widening Primitive Conversions
*/
public double doubleValue() {
return (double)value;
@@ -650,8 +648,9 @@
*
* @return a hash code value for this object.
*/
+ @Override
public int hashCode() {
- return floatToIntBits(value);
+ return Float.hashCode(value);
}
/**
@@ -815,13 +814,13 @@
* <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three
* values that can be computed from the argument:
*
- * <blockquote><pre>
- * int s = ((bits >> 31) == 0) ? 1 : -1;
- * int e = ((bits >> 23) & 0xff);
+ * <blockquote><pre>{@code
+ * int s = ((bits >> 31) == 0) ? 1 : -1;
+ * int e = ((bits >> 23) & 0xff);
* int m = (e == 0) ?
- * (bits & 0x7fffff) << 1 :
+ * (bits & 0x7fffff) << 1 :
* (bits & 0x7fffff) | 0x800000;
- * </pre></blockquote>
+ * }</pre></blockquote>
*
* Then the floating-point result equals the value of the mathematical
* expression <i>s</i>·<i>m</i>·2<sup><i>e</i>-150</sup>.
diff --git a/ojluni/src/main/java/java/lang/FloatingDecimal.java b/ojluni/src/main/java/java/lang/FloatingDecimal.java
deleted file mode 100755
index d27c5ae..0000000
--- a/ojluni/src/main/java/java/lang/FloatingDecimal.java
+++ /dev/null
@@ -1,2476 +0,0 @@
- /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-import sun.misc.FpUtils;
-import sun.misc.FDBigInt;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import java.util.regex.*;
-
-public class FloatingDecimal {
- boolean isExceptional;
- boolean isNegative;
- int decExponent;
- char digits[];
- int nDigits;
- int bigIntExp;
- int bigIntNBits;
- boolean mustSetRoundDir = false;
- boolean fromHex = false;
- int roundDir = 0; // set by doubleValue
-
- /*
- * Constants of the implementation
- * Most are IEEE-754 related.
- * (There are more really boring constants at the end.)
- */
- static final long signMask = 0x8000000000000000L;
- static final long expMask = 0x7ff0000000000000L;
- static final long fractMask= ~(signMask|expMask);
- static final int expShift = 52;
- static final int expBias = 1023;
- static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit
- static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
- static final int maxSmallBinExp = 62;
- static final int minSmallBinExp = -( 63 / 3 );
- static final int maxDecimalDigits = 15;
- static final int maxDecimalExponent = 308;
- static final int minDecimalExponent = -324;
- static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
-
- static final long highbyte = 0xff00000000000000L;
- static final long highbit = 0x8000000000000000L;
- static final long lowbytes = ~highbyte;
-
- static final int singleSignMask = 0x80000000;
- static final int singleExpMask = 0x7f800000;
- static final int singleFractMask = ~(singleSignMask|singleExpMask);
- static final int singleExpShift = 23;
- static final int singleFractHOB = 1<<singleExpShift;
- static final int singleExpBias = 127;
- static final int singleMaxDecimalDigits = 7;
- static final int singleMaxDecimalExponent = 38;
- static final int singleMinDecimalExponent = -45;
-
- static final int intDecimalDigits = 9;
-
- /*
- * count number of bits from high-order 1 bit to low-order 1 bit,
- * inclusive.
- */
- private static int
- countBits( long v ){
- //
- // the strategy is to shift until we get a non-zero sign bit
- // then shift until we have no bits left, counting the difference.
- // we do byte shifting as a hack. Hope it helps.
- //
- if ( v == 0L ) return 0;
-
- while ( ( v & highbyte ) == 0L ){
- v <<= 8;
- }
- while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
- v <<= 1;
- }
-
- int n = 0;
- while (( v & lowbytes ) != 0L ){
- v <<= 8;
- n += 8;
- }
- while ( v != 0L ){
- v <<= 1;
- n += 1;
- }
- return n;
- }
-
- /*
- * Keep big powers of 5 handy for future reference.
- */
- private static FDBigInt b5p[];
-
- private static synchronized FDBigInt
- big5pow( int p ){
- assert p >= 0 : p; // negative power of 5
- if ( b5p == null ){
- b5p = new FDBigInt[ p+1 ];
- }else if (b5p.length <= p ){
- FDBigInt t[] = new FDBigInt[ p+1 ];
- System.arraycopy( b5p, 0, t, 0, b5p.length );
- b5p = t;
- }
- if ( b5p[p] != null )
- return b5p[p];
- else if ( p < small5pow.length )
- return b5p[p] = new FDBigInt( small5pow[p] );
- else if ( p < long5pow.length )
- return b5p[p] = new FDBigInt( long5pow[p] );
- else {
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- FDBigInt bigq = b5p[q];
- if ( bigq == null )
- bigq = big5pow ( q );
- if ( r < small5pow.length ){
- return (b5p[p] = bigq.mult( small5pow[r] ) );
- }else{
- FDBigInt bigr = b5p[ r ];
- if ( bigr == null )
- bigr = big5pow( r );
- return (b5p[p] = bigq.mult( bigr ) );
- }
- }
- }
-
- //
- // a common operation
- //
- private static FDBigInt
- multPow52( FDBigInt v, int p5, int p2 ){
- if ( p5 != 0 ){
- if ( p5 < small5pow.length ){
- v = v.mult( small5pow[p5] );
- } else {
- v = v.mult( big5pow( p5 ) );
- }
- }
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- //
- // another common operation
- //
- private static FDBigInt
- constructPow52( int p5, int p2 ){
- FDBigInt v = new FDBigInt( big5pow( p5 ) );
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- /*
- * Make a floating double into a FDBigInt.
- * This could also be structured as a FDBigInt
- * constructor, but we'd have to build a lot of knowledge
- * about floating-point representation into it, and we don't want to.
- *
- * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- *
- */
- private FDBigInt
- doubleToBigInt( double dval ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- lbits &= fractMask;
- if ( binexp > 0 ){
- lbits |= fractHOB;
- } else {
- assert lbits != 0L : lbits; // doubleToBigInt(0.0)
- binexp +=1;
- while ( (lbits & fractHOB ) == 0L){
- lbits <<= 1;
- binexp -= 1;
- }
- }
- binexp -= expBias;
- int nbits = countBits( lbits );
- /*
- * We now know where the high-order 1 bit is,
- * and we know how many there are.
- */
- int lowOrderZeros = expShift+1-nbits;
- lbits >>>= lowOrderZeros;
-
- bigIntExp = binexp+1-nbits;
- bigIntNBits = nbits;
- return new FDBigInt( lbits );
- }
-
- /*
- * Compute a number that is the ULP of the given value,
- * for purposes of addition/subtraction. Generally easy.
- * More difficult if subtracting and the argument
- * is a normalized a power of 2, as the ULP changes at these points.
- */
- private static double ulp( double dval, boolean subtracting ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- double ulpval;
- if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
- // for subtraction from normalized, powers of 2,
- // use next-smaller exponent
- binexp -= 1;
- }
- if ( binexp > expShift ){
- ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
- } else if ( binexp == 0 ){
- ulpval = Double.MIN_VALUE;
- } else {
- ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
- }
- if ( subtracting ) ulpval = - ulpval;
-
- return ulpval;
- }
-
- /*
- * Round a double to a float.
- * In addition to the fraction bits of the double,
- * look at the class instance variable roundDir,
- * which should help us avoid double-rounding error.
- * roundDir was set in hardValueOf if the estimate was
- * close enough, but not exact. It tells us which direction
- * of rounding is preferred.
- */
- float
- stickyRound( double dval ){
- long lbits = Double.doubleToLongBits( dval );
- long binexp = lbits & expMask;
- if ( binexp == 0L || binexp == expMask ){
- // what we have here is special.
- // don't worry, the right thing will happen.
- return (float) dval;
- }
- lbits += (long)roundDir; // hack-o-matic.
- return (float)Double.longBitsToDouble( lbits );
- }
-
-
- /*
- * This is the easy subcase --
- * all the significant bits, after scaling, are held in lvalue.
- * negSign and decExponent tell us what processing and scaling
- * has already been done. Exceptional cases have already been
- * stripped out.
- * In particular:
- * lvalue is a finite number (not Inf, nor NaN)
- * lvalue > 0L (not zero, nor negative).
- *
- * The only reason that we develop the digits here, rather than
- * calling on Long.toString() is that we can do it a little faster,
- * and besides want to treat trailing 0s specially. If Long.toString
- * changes, we should re-evaluate this strategy!
- */
- private void
- developLongDigits( int decExponent, long lvalue, long insignificant ){
- char digits[];
- int ndigits;
- int digitno;
- int c;
- //
- // Discard non-significant low-order bits, while rounding,
- // up to insignificant value.
- int i;
- for ( i = 0; insignificant >= 10L; i++ )
- insignificant /= 10L;
- if ( i != 0 ){
- long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
- long residue = lvalue % pow10;
- lvalue /= pow10;
- decExponent += i;
- if ( residue >= (pow10>>1) ){
- // round up based on the low-order bits we're discarding
- lvalue++;
- }
- }
- if ( lvalue <= Integer.MAX_VALUE ){
- assert lvalue > 0L : lvalue; // lvalue <= 0
- // even easier subcase!
- // can do int arithmetic rather than long!
- int ivalue = (int)lvalue;
- ndigits = 10;
- digits = (char[])(perThreadBuffer.get());
- digitno = ndigits-1;
- c = ivalue%10;
- ivalue /= 10;
- while ( c == 0 ){
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- } else {
- // same algorithm as above (same bugs, too )
- // but using long arithmetic.
- ndigits = 20;
- digits = (char[])(perThreadBuffer.get());
- digitno = ndigits-1;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- while ( c == 0 ){
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- }
- while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- }
- char result [];
- ndigits -= digitno;
- result = new char[ ndigits ];
- System.arraycopy( digits, digitno, result, 0, ndigits );
- this.digits = result;
- this.decExponent = decExponent+1;
- this.nDigits = ndigits;
- }
-
- //
- // add one to the least significant digit.
- // in the unlikely event there is a carry out,
- // deal with it.
- // assert that this will only happen where there
- // is only one digit, e.g. (float)1e-44 seems to do it.
- //
- private void
- roundup(){
- int i;
- int q = digits[ i = (nDigits-1)];
- if ( q == '9' ){
- while ( q == '9' && i > 0 ){
- digits[i] = '0';
- q = digits[--i];
- }
- if ( q == '9' ){
- // carryout! High-order 1, rest 0s, larger exp.
- decExponent += 1;
- digits[0] = '1';
- return;
- }
- // else fall through.
- }
- digits[i] = (char)(q+1);
- }
-
- private FloatingDecimal() {}
-
- private static final ThreadLocal<FloatingDecimal> TL_INSTANCE = new ThreadLocal<FloatingDecimal>() {
- @Override protected FloatingDecimal initialValue() {
- return new FloatingDecimal();
- }
- };
- public static FloatingDecimal getThreadLocalInstance() {
- return TL_INSTANCE.get();
- }
-
- /*
- * FIRST IMPORTANT LOAD: DOUBLE
- */
- public FloatingDecimal loadDouble(double d) {
- long dBits = Double.doubleToLongBits( d );
- long fractBits;
- int binExp;
- int nSignificantBits;
-
- mustSetRoundDir = false;
- fromHex = false;
- roundDir = 0;
-
- // discover and delete sign
- if ( (dBits&signMask) != 0 ){
- isNegative = true;
- dBits ^= signMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (dBits&expMask) >> expShift );
- fractBits = dBits&fractMask;
- if ( binExp == (int)(expMask>>expShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return this;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return this;
- }
- while ( (fractBits&fractHOB) == 0L ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= fractHOB;
- nSignificantBits = expShift+1;
- }
- binExp -= expBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, fractBits, nSignificantBits );
- return this;
- }
-
- /*
- * SECOND IMPORTANT LOAD: SINGLE
- */
- public FloatingDecimal loadFloat(float f) {
- int fBits = Float.floatToIntBits( f );
- int fractBits;
- int binExp;
- int nSignificantBits;
-
- mustSetRoundDir = false;
- fromHex = false;
- roundDir = 0;
-
- // discover and delete sign
- if ( (fBits&singleSignMask) != 0 ){
- isNegative = true;
- fBits ^= singleSignMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (fBits&singleExpMask) >> singleExpShift );
- fractBits = fBits&singleFractMask;
- if ( binExp == (int)(singleExpMask>>singleExpShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return this;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return this;
- }
- while ( (fractBits&singleFractHOB) == 0 ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= singleFractHOB;
- nSignificantBits = singleExpShift+1;
- }
- binExp -= singleExpBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
- return this;
- }
-
- private void
- dtoa( int binExp, long fractBits, int nSignificantBits )
- {
- int nFractBits; // number of significant bits of fractBits;
- int nTinyBits; // number of these to the right of the point.
- int decExp;
-
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- nFractBits = countBits( fractBits );
- nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
- /*
- * We can do this:
- * take the fraction bits, which are normalized.
- * (a) nTinyBits == 0: Shift left or right appropriately
- * to align the binary point at the extreme right, i.e.
- * where a long int point is expected to be. The integer
- * result is easily converted to a string.
- * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
- * which effectively converts to long and scales by
- * 2^nTinyBits. Then multiply by 5^nTinyBits to
- * complete the scaling. We know this won't overflow
- * because we just counted the number of bits necessary
- * in the result. The integer you get from this can
- * then be converted to a string pretty easily.
- */
- long halfULP;
- if ( nTinyBits == 0 ) {
- if ( binExp > nSignificantBits ){
- halfULP = 1L << ( binExp-nSignificantBits-1);
- } else {
- halfULP = 0L;
- }
- if ( binExp >= expShift ){
- fractBits <<= (binExp-expShift);
- } else {
- fractBits >>>= (expShift-binExp) ;
- }
- developLongDigits( 0, fractBits, halfULP );
- return;
- }
- /*
- * The following causes excess digits to be printed
- * out in the single-float case. Our manipulation of
- * halfULP here is apparently not correct. If we
- * better understand how this works, perhaps we can
- * use this special case again. But for the time being,
- * we do not.
- * else {
- * fractBits >>>= expShift+1-nFractBits;
- * fractBits *= long5pow[ nTinyBits ];
- * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- * developLongDigits( -nTinyBits, fractBits, halfULP );
- * return;
- * }
- */
- }
- }
- /*
- * This is the hard case. We are going to compute large positive
- * integers B and S and integer decExp, s.t.
- * d = ( B / S ) * 10^decExp
- * 1 <= B / S < 10
- * Obvious choices are:
- * decExp = floor( log10(d) )
- * B = d * 2^nTinyBits * 10^max( 0, -decExp )
- * S = 10^max( 0, decExp) * 2^nTinyBits
- * (noting that nTinyBits has already been forced to non-negative)
- * I am also going to compute a large positive integer
- * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
- * i.e. M is (1/2) of the ULP of d, scaled like B.
- * When we iterate through dividing B/S and picking off the
- * quotient bits, we will know when to stop when the remainder
- * is <= M.
- *
- * We keep track of powers of 2 and powers of 5.
- */
-
- /*
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- * FIXME -- use more precise constants here. It costs no more.
- */
- double d2 = Double.longBitsToDouble(
- expOne | ( fractBits &~ fractHOB ) );
- decExp = (int)Math.floor(
- (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
- int Bbits; // binary digits needed to represent B, approx.
- int tenSbits; // binary digits needed to represent 10*S, approx.
- FDBigInt Sval, Bval, Mval;
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- /*
- * the long integer fractBits contains the (nFractBits) interesting
- * bits from the mantissa of d ( hidden 1 added if necessary) followed
- * by (expShift+1-nFractBits) zeros. In the interest of compactness,
- * I will shift out those zeros before turning fractBits into a
- * FDBigInt. The resulting whole number will be
- * d * 2^(nFractBits-1-binExp).
- */
- fractBits >>>= (expShift+1-nFractBits);
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- /*
- * HACK!! For exact powers of two, the next smallest number
- * is only half as far away as we think (because the meaning of
- * ULP changes at power-of-two bounds) for this reason, we
- * hack M2. Hope this works.
- */
- if ( nFractBits == 1 )
- M2 -= 1;
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- /*
- * Construct, Scale, iterate.
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- char digits[] = this.digits = new char[18];
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- /*
- * Detect the special cases where all the numbers we are about
- * to compute will fit in int or long integers.
- * In these cases, we will avoid doing FDBigInt arithmetic.
- * We use the same algorithms, except that we "normalize"
- * our FDBigInts before iterating. This is to make division easier,
- * as it makes our fist guess (quotient of high-order words)
- * more accurate!
- *
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
- tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * small5pow[B5] ) << B2;
- int s = small5pow[S5] << S2;
- int m = small5pow[M5] << M2;
- int tens = s * 10;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- } else {
- // still good! they're all longs!
- long b = (fractBits * long5pow[B5] ) << B2;
- long s = long5pow[S5] << S2;
- long m = long5pow[M5] << M2;
- long tens = s * 10L;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- }
- } else {
- FDBigInt tenSval;
- int shiftBias;
-
- /*
- * We really must do FDBigInt arithmetic.
- * Fist, construct our FDBigInt initial values.
- */
- Bval = multPow52( new FDBigInt( fractBits ), B5, B2 );
- Sval = constructPow52( S5, S2 );
- Mval = constructPow52( M5, M2 );
-
-
- // normalize so that division works better
- Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
- Mval.lshiftMe( shiftBias );
- tenSval = Sval.mult( 10 );
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- assert q < 10 : q; // excessively large digit
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval.lshiftMe(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else
- lowDigitDifference = 0L; // this here only for flow analysis!
- }
- this.decExponent = decExp+1;
- this.digits = digits;
- this.nDigits = ndigit;
- /*
- * Last digit gets rounded based on stopping condition.
- */
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[nDigits-1]&1) != 0 ) roundup();
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- public String
- toString(){
- // most brain-dead version
- StringBuffer result = new StringBuffer( nDigits+8 );
- if ( isNegative ){ result.append( '-' ); }
- if ( isExceptional ){
- result.append( digits, 0, nDigits );
- } else {
- result.append( "0.");
- result.append( digits, 0, nDigits );
- result.append('e');
- result.append( decExponent );
- }
- return new String(result);
- }
-
- public String toJavaFormatString() {
- char result[] = (char[])(perThreadBuffer.get());
- int i = getChars(result);
- return new String(result, 0, i);
- }
-
- private int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) { result[0] = '-'; i = 1; }
- if (isExceptional) {
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- if (decExponent > 0 && decExponent < 8) {
- // case with digits.digits
- int charLength = Math.min(nDigits, decExponent);
- System.arraycopy(digits, 0, result, i, charLength);
- i += charLength;
- if (charLength < decExponent) {
- charLength = decExponent-charLength;
- System.arraycopy(zero, 0, result, i, charLength);
- i += charLength;
- result[i++] = '.';
- result[i++] = '0';
- } else {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = nDigits - charLength;
- System.arraycopy(digits, charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- }
- } else if (decExponent <=0 && decExponent > -3) {
- // case with 0.digits
- result[i++] = '0';
- result[i++] = '.';
- if (decExponent != 0) {
- System.arraycopy(zero, 0, result, i, -decExponent);
- i -= decExponent;
- }
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- // case with digit.digitsEexponent
- result[i++] = digits[0];
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, 1, result, i, nDigits-1);
- i += nDigits-1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- int e;
- if (decExponent <= 0) {
- result[i++] = '-';
- e = -decExponent+1;
- } else {
- e = decExponent-1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- result[i++] = (char)(e+'0');
- } else if (e <= 99) {
- result[i++] = (char)(e/10 +'0');
- result[i++] = (char)(e%10 + '0');
- } else {
- result[i++] = (char)(e/100+'0');
- e %= 100;
- result[i++] = (char)(e/10+'0');
- result[i++] = (char)(e%10 + '0');
- }
- }
- }
- return i;
- }
-
- // Per-thread buffer for string/stringbuffer conversion
- private static ThreadLocal perThreadBuffer = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new char[26];
- }
- };
-
- public void appendTo(AbstractStringBuilder buf) {
- if (isNegative) { buf.append('-'); }
- if (isExceptional) {
- buf.append(digits, 0 , nDigits);
- return;
- }
- if (decExponent > 0 && decExponent < 8) {
- // print digits.digits.
- int charLength = Math.min(nDigits, decExponent);
- buf.append(digits, 0 , charLength);
- if (charLength < decExponent) {
- charLength = decExponent-charLength;
- buf.append(zero, 0 , charLength);
- buf.append(".0");
- } else {
- buf.append('.');
- if (charLength < nDigits) {
- buf.append(digits, charLength, nDigits - charLength);
- } else {
- buf.append('0');
- }
- }
- } else if (decExponent <=0 && decExponent > -3) {
- buf.append("0.");
- if (decExponent != 0) {
- buf.append(zero, 0, -decExponent);
- }
- buf.append(digits, 0, nDigits);
- } else {
- buf.append(digits[0]);
- buf.append('.');
- if (nDigits > 1) {
- buf.append(digits, 1, nDigits-1);
- } else {
- buf.append('0');
- }
- buf.append('E');
- int e;
- if (decExponent <= 0) {
- buf.append('-');
- e = -decExponent + 1;
- } else {
- e = decExponent - 1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- buf.append((char)(e + '0'));
- } else if (e <= 99) {
- buf.append((char)(e/10 + '0'));
- buf.append((char)(e%10 + '0'));
- } else {
- buf.append((char)(e/100 + '0'));
- e %= 100;
- buf.append((char)(e/10 + '0'));
- buf.append((char)(e%10 + '0'));
- }
- }
- }
-
- public FloatingDecimal
- readJavaFormatString( String in ) throws NumberFormatException {
- boolean isNegative = false;
- boolean signSeen = false;
- int decExp;
- char c;
-
- parseNumber:
- try{
- in = in.trim(); // don't fool around with white space.
- // throws NullPointerException if null
- int l = in.length();
- if ( l == 0 ) throw new NumberFormatException("empty String");
- int i = 0;
- switch ( c = in.charAt( i ) ){
- case '-':
- isNegative = true;
- //FALLTHROUGH
- case '+':
- i++;
- signSeen = true;
- }
-
- // Check for NaN and Infinity strings
- c = in.charAt(i);
- if(c == 'N' || c == 'I') { // possible NaN or infinity
- boolean potentialNaN = false;
- char targetChars[] = null; // char array of "NaN" or "Infinity"
-
- if(c == 'N') {
- targetChars = notANumber;
- potentialNaN = true;
- } else {
- targetChars = infinity;
- }
-
- // compare Input string to "NaN" or "Infinity"
- int j = 0;
- while(i < l && j < targetChars.length) {
- if(in.charAt(i) == targetChars[j]) {
- i++; j++;
- }
- else // something is amiss, throw exception
- break parseNumber;
- }
-
- // For the candidate string to be a NaN or infinity,
- // all characters in input string and target char[]
- // must be matched ==> j must equal targetChars.length
- // and i must equal l
- if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
- return (potentialNaN ? loadDouble(Double.NaN) // NaN has no sign
- : loadDouble(isNegative?
- Double.NEGATIVE_INFINITY:
- Double.POSITIVE_INFINITY)) ;
- }
- else { // something went wrong, throw exception
- break parseNumber;
- }
-
- } else if (c == '0') { // check for hexadecimal floating-point number
- if (l > i+1 ) {
- char ch = in.charAt(i+1);
- if (ch == 'x' || ch == 'X' ) // possible hex string
- return parseHexString(in);
- }
- } // look for and process decimal floating-point string
-
- char[] digits = new char[ l ];
- int nDigits= 0;
- boolean decSeen = false;
- int decPt = 0;
- int nLeadZero = 0;
- int nTrailZero= 0;
- digitLoop:
- while ( i < l ){
- switch ( c = in.charAt( i ) ){
- case '0':
- if ( nDigits > 0 ){
- nTrailZero += 1;
- } else {
- nLeadZero += 1;
- }
- break; // out of switch.
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- while ( nTrailZero > 0 ){
- digits[nDigits++] = '0';
- nTrailZero -= 1;
- }
- digits[nDigits++] = c;
- break; // out of switch.
- case '.':
- if ( decSeen ){
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if ( signSeen ){
- decPt -= 1;
- }
- decSeen = true;
- break; // out of switch.
- default:
- break digitLoop;
- }
- i++;
- }
- /*
- * At this point, we've scanned all the digits and decimal
- * point we're going to see. Trim off leading and trailing
- * zeros, which will just confuse us later, and adjust
- * our initial decimal exponent accordingly.
- * To review:
- * we have seen i total characters.
- * nLeadZero of them were zeros before any other digits.
- * nTrailZero of them were zeros after any other digits.
- * if ( decSeen ), then a . was seen after decPt characters
- * ( including leading zeros which have been discarded )
- * nDigits characters were neither lead nor trailing
- * zeros, nor point
- */
- /*
- * special hack: if we saw no non-zero digits, then the
- * answer is zero!
- * Unfortunately, we feel honor-bound to keep parsing!
- */
- if ( nDigits == 0 ){
- digits = zero;
- nDigits = 1;
- if ( nLeadZero == 0 ){
- // we saw NO DIGITS AT ALL,
- // not even a crummy 0!
- // this is not allowed.
- break parseNumber; // go throw exception
- }
-
- }
-
- /* Our initial exponent is decPt, adjusted by the number of
- * discarded zeros. Or, if there was no decPt,
- * then its just nDigits adjusted by discarded trailing zeros.
- */
- if ( decSeen ){
- decExp = decPt - nLeadZero;
- } else {
- decExp = nDigits+nTrailZero;
- }
-
- /*
- * Look for 'e' or 'E' and an optionally signed integer.
- */
- if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
- int expSign = 1;
- int expVal = 0;
- int reallyBig = Integer.MAX_VALUE / 10;
- boolean expOverflow = false;
- switch( in.charAt(++i) ){
- case '-':
- expSign = -1;
- //FALLTHROUGH
- case '+':
- i++;
- }
- int expAt = i;
- expLoop:
- while ( i < l ){
- if ( expVal >= reallyBig ){
- // the next character will cause integer
- // overflow.
- expOverflow = true;
- }
- switch ( c = in.charAt(i++) ){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- expVal = expVal*10 + ( (int)c - (int)'0' );
- continue;
- default:
- i--; // back up.
- break expLoop; // stop parsing exponent.
- }
- }
- int expLimit = bigDecimalExponent+nDigits+nTrailZero;
- if ( expOverflow || ( expVal > expLimit ) ){
- //
- // The intent here is to end up with
- // infinity or zero, as appropriate.
- // The reason for yielding such a small decExponent,
- // rather than something intuitive such as
- // expSign*Integer.MAX_VALUE, is that this value
- // is subject to further manipulation in
- // doubleValue() and floatValue(), and I don't want
- // it to be able to cause overflow there!
- // (The only way we can get into trouble here is for
- // really outrageous nDigits+nTrailZero, such as 2 billion. )
- //
- decExp = expSign*expLimit;
- } else {
- // this should not overflow, since we tested
- // for expVal > (MAX+N), where N >= abs(decExp)
- decExp = decExp + expSign*expVal;
- }
-
- // if we saw something not a digit ( or end of string )
- // after the [Ee][+-], without seeing any digits at all
- // this is certainly an error. If we saw some digits,
- // but then some trailing garbage, that might be ok.
- // so we just fall through in that case.
- // HUMBUG
- if ( i == expAt )
- break parseNumber; // certainly bad
- }
- /*
- * We parsed everything we could.
- * If there are leftovers, then this is not good input!
- */
- if ( i < l &&
- ((i != l - 1) ||
- (in.charAt(i) != 'f' &&
- in.charAt(i) != 'F' &&
- in.charAt(i) != 'd' &&
- in.charAt(i) != 'D'))) {
- break parseNumber; // go throw exception
- }
-
- this.isNegative = isNegative;
- this.decExponent = decExp;
- this.digits = digits;
- this.nDigits = nDigits;
- this.isExceptional = false;
- return this;
- } catch ( StringIndexOutOfBoundsException e ){ }
- throw new NumberFormatException("For input string: \"" + in + "\"");
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
- */
-
- public strictfp double doubleValue(){
- int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
- long lValue;
- double dValue;
- double rValue, tValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Double.NaN;
- else
- return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
- }
- else {
- if (mustSetRoundDir) {
- roundDir = 0;
- }
- /*
- * convert the lead kDigits to a long integer.
- */
- // (special performance hack: start to do it using int)
- int iValue = (int)digits[0]-(int)'0';
- int iDigits = Math.min( kDigits, intDecimalDigits );
- for ( int i=1; i < iDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- lValue = (long)iValue;
- for ( int i=iDigits; i < kDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- dValue = (double)lValue;
- int exp = decExponent-kDigits;
- /*
- * lValue now contains a long integer with the value of
- * the first kDigits digits of the number.
- * dValue contains the (double) of the same.
- */
-
- if ( nDigits <= maxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here
- */
- if (exp == 0 || dValue == 0.0)
- return (isNegative)? -dValue : dValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= maxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- rValue = dValue * small10pow[exp];
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- int slop = maxDecimalDigits - kDigits;
- if ( exp <= maxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- dValue *= small10pow[slop];
- rValue = dValue * small10pow[exp-slop];
-
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp-slop];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -maxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- rValue = dValue / small10pow[-exp];
- tValue = rValue * small10pow[-exp];
- if ( mustSetRoundDir ){
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- }
-
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by approximating the right answer by,
- * naively, scaling by powers of 10.
- */
- if ( exp > 0 ){
- if ( decExponent > maxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ( (exp&15) != 0 ){
- dValue *= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= big10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could overflow.
- */
- double t = dValue * big10pow[j];
- if ( Double.isInfinite( t ) ){
- /*
- * It did overflow.
- * Look more closely at the result.
- * If the exponent is just one too large,
- * then use the maximum finite as our estimate
- * value. Else call the result infinity
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two larger than
- * Double.MAX_VALUE ).
- */
- t = dValue / 2.0;
- t *= big10pow[j];
- if ( Double.isInfinite( t ) ){
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if ( exp < 0 ){
- exp = -exp;
- if ( decExponent < minDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0 : 0.0;
- }
- if ( (exp&15) != 0 ){
- dValue /= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= tiny10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could underflow.
- */
- double t = dValue * tiny10pow[j];
- if ( t == 0.0 ){
- /*
- * It did underflow.
- * Look more closely at the result.
- * If the exponent is just one too small,
- * then use the minimum finite as our estimate
- * value. Else call the result 0.0
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two less than
- * Double.MIN_VALUE ).
- */
- t = dValue * 2.0;
- t *= tiny10pow[j];
- if ( t == 0.0 ){
- return (isNegative)? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- /*
- * dValue is now approximately the result.
- * The hard part is adjusting it, by comparison
- * with FDBigInt arithmetic.
- * Formulate the EXACT big-number result as
- * bigD0 * 10^exp
- */
- FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
- exp = decExponent - nDigits;
-
- correctionLoop:
- while(true){
- /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- */
- FDBigInt bigB = doubleToBigInt( dValue );
-
- /*
- * Scale bigD, bigB appropriately for
- * big-integer operations.
- * Naively, we multiply by powers of ten
- * and powers of two. What we actually do
- * is keep track of the powers of 5 and
- * powers of 2 we would use, then factor out
- * common divisors before doing the work.
- */
- int B2, B5; // powers of 2, 5 in bigB
- int D2, D5; // powers of 2, 5 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if ( exp >= 0 ){
- B2 = B5 = 0;
- D2 = D5 = exp;
- } else {
- B2 = B5 = -exp;
- D2 = D5 = 0;
- }
- if ( bigIntExp >= 0 ){
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if ( bigIntExp+bigIntNBits <= -expBias+1 ){
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(expBias+expShift+1)
- hulpbias = bigIntExp+ expBias + expShift;
- } else {
- hulpbias = expShift + 2 - bigIntNBits;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- bigB = multPow52( bigB, B5, B2 );
- FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInt diff;
- int cmpResult;
- boolean overvalue;
- if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
- overvalue = true; // our candidate is too big.
- diff = bigB.sub( bigD );
- if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
- // candidate is a normalized exact power of 2 and
- // is too big. We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if ( Ulp2 < 0 ){
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff.lshiftMe( 1 );
- }
- }
- } else if ( cmpResult < 0 ){
- overvalue = false; // our candidate is too small.
- diff = bigD.sub( bigB );
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- FDBigInt halfUlp = constructPow52( B5, Ulp2 );
- if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
- // difference is small.
- // this is close enough
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else if ( cmpResult == 0 ){
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- dValue += 0.5*ulp( dValue, overvalue );
- // should check for bigIntNBits == 1 here??
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- dValue += ulp( dValue, overvalue );
- if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
- break correctionLoop; // oops. Fell off end of range.
- continue; // try again.
- }
-
- }
- return (isNegative)? -dValue : dValue;
- }
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the conversion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
- */
-
- public strictfp float floatValue(){
- int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
- int iValue;
- float fValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Float.NaN;
- else
- return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
- }
- else {
- /*
- * convert the lead kDigits to an integer.
- */
- iValue = (int)digits[0]-(int)'0';
- for ( int i=1; i < kDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- fValue = (float)iValue;
- int exp = decExponent-kDigits;
- /*
- * iValue now contains an integer with the value of
- * the first kDigits digits of the number.
- * fValue contains the (float) of the same.
- */
-
- if ( nDigits <= singleMaxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here.
- */
- if (exp == 0 || fValue == 0.0f)
- return (isNegative)? -fValue : fValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= singleMaxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- fValue *= singleSmall10pow[exp];
- return (isNegative)? -fValue : fValue;
- }
- int slop = singleMaxDecimalDigits - kDigits;
- if ( exp <= singleMaxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- fValue *= singleSmall10pow[slop];
- fValue *= singleSmall10pow[exp-slop];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -singleMaxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- fValue /= singleSmall10pow[-exp];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
- /*
- * In double-precision, this is an exact floating integer.
- * So we can compute to double, then shorten to float
- * with one round, and get the right answer.
- *
- * First, finish accumulating digits.
- * Then convert that integer to a double, multiply
- * by the appropriate power of ten, and convert to float.
- */
- long lValue = (long)iValue;
- for ( int i=kDigits; i < nDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- double dValue = (double)lValue;
- exp = decExponent-nDigits;
- dValue *= small10pow[exp];
- fValue = (float)dValue;
- return (isNegative)? -fValue : fValue;
-
- }
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by weeding out obviously out-of-range
- * results, then convert to double and go to
- * common hard-case code.
- */
- if ( decExponent > singleMaxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- } else if ( decExponent < singleMinDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0f : 0.0f;
- }
-
- /*
- * Here, we do 'way too much work, but throwing away
- * our partial results, and going and doing the whole
- * thing as double, then throwing away half the bits that computes
- * when we convert back to float.
- *
- * The alternative is to reproduce the whole multiple-precision
- * algorithm for float precision, or to try to parameterize it
- * for common usage. The former will take about 400 lines of code,
- * and the latter I tried without success. Thus the semi-hack
- * answer here.
- */
- mustSetRoundDir = !fromHex;
- double dValue = doubleValue();
- return stickyRound( dValue );
- }
- }
-
-
- /*
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
- */
- private static final double small10pow[] = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float singleSmall10pow[] = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double big10pow[] = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double tiny10pow[] = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int maxSmallTen = small10pow.length-1;
- private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
- private static final int small5pow[] = {
- 1,
- 5,
- 5*5,
- 5*5*5,
- 5*5*5*5,
- 5*5*5*5*5,
- 5*5*5*5*5*5,
- 5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5*5
- };
-
-
- private static final long long5pow[] = {
- 1L,
- 5L,
- 5L*5,
- 5L*5*5,
- 5L*5*5*5,
- 5L*5*5*5*5,
- 5L*5*5*5*5*5,
- 5L*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int n5bits[] = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
- private static final char notANumber[] = { 'N', 'a', 'N' };
- private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
-
-
- /*
- * Grammar is compatible with hexadecimal floating-point constants
- * described in section 6.4.4.2 of the C99 specification.
- */
- private static Pattern hexFloatPattern = null;
- private static synchronized Pattern getHexFloatPattern() {
- if (hexFloatPattern == null) {
- hexFloatPattern = Pattern.compile(
- //1 234 56 7 8 9
- "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
- );
- }
- return hexFloatPattern;
- }
-
- /*
- * Convert string s to a suitable floating decimal; uses the
- * double constructor and set the roundDir variable appropriately
- * in case the value is later converted to a float.
- */
- FloatingDecimal parseHexString(String s) {
- // Verify string is a member of the hexadecimal floating-point
- // string language.
- Matcher m = getHexFloatPattern().matcher(s);
- boolean validInput = m.matches();
-
- if (!validInput) {
- // Input does not match pattern
- throw new NumberFormatException("For input string: \"" + s + "\"");
- } else { // validInput
- /*
- * We must isolate the sign, significand, and exponent
- * fields. The sign value is straightforward. Since
- * floating-point numbers are stored with a normalized
- * representation, the significand and exponent are
- * interrelated.
- *
- * After extracting the sign, we normalized the
- * significand as a hexadecimal value, calculating an
- * exponent adjust for any shifts made during
- * normalization. If the significand is zero, the
- * exponent doesn't need to be examined since the output
- * will be zero.
- *
- * Next the exponent in the input string is extracted.
- * Afterwards, the significand is normalized as a *binary*
- * value and the input value's normalized exponent can be
- * computed. The significand bits are copied into a
- * double significand; if the string has more logical bits
- * than can fit in a double, the extra bits affect the
- * round and sticky bits which are used to round the final
- * value.
- */
-
- // Extract significand sign
- String group1 = m.group(1);
- double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
-
-
- // Extract Significand magnitude
- /*
- * Based on the form of the significand, calculate how the
- * binary exponent needs to be adjusted to create a
- * normalized *hexadecimal* floating-point number; that
- * is, a number where there is one nonzero hex digit to
- * the left of the (hexa)decimal point. Since we are
- * adjusting a binary, not hexadecimal exponent, the
- * exponent is adjusted by a multiple of 4.
- *
- * There are a number of significand scenarios to consider;
- * letters are used in indicate nonzero digits:
- *
- * 1. 000xxxx => x.xxx normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 2. 000xxx.yyyy => x.xxyyyy normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 3. .000yyy => y.yy normalized
- * decrease exponent by (number of zeros + 1)*4
- *
- * 4. 000.00000yyy => y.yy normalized
- * decrease exponent by (number of zeros to right of point + 1)*4
- *
- * If the significand is exactly zero, return a properly
- * signed zero.
- */
-
- String significandString =null;
- int signifLength = 0;
- int exponentAdjust = 0;
- {
- int leftDigits = 0; // number of meaningful digits to
- // left of "decimal" point
- // (leading zeros stripped)
- int rightDigits = 0; // number of digits to right of
- // "decimal" point; leading zeros
- // must always be accounted for
- /*
- * The significand is made up of either
- *
- * 1. group 4 entirely (integer portion only)
- *
- * OR
- *
- * 2. the fractional portion from group 7 plus any
- * (optional) integer portions from group 6.
- */
- String group4;
- if( (group4 = m.group(4)) != null) { // Integer-only significand
- // Leading zeros never matter on the integer portion
- significandString = stripLeadingZeros(group4);
- leftDigits = significandString.length();
- }
- else {
- // Group 6 is the optional integer; leading zeros
- // never matter on the integer portion
- String group6 = stripLeadingZeros(m.group(6));
- leftDigits = group6.length();
-
- // fraction
- String group7 = m.group(7);
- rightDigits = group7.length();
-
- // Turn "integer.fraction" into "integer"+"fraction"
- significandString =
- ((group6 == null)?"":group6) + // is the null
- // check necessary?
- group7;
- }
-
- significandString = stripLeadingZeros(significandString);
- signifLength = significandString.length();
-
- /*
- * Adjust exponent as described above
- */
- if (leftDigits >= 1) { // Cases 1 and 2
- exponentAdjust = 4*(leftDigits - 1);
- } else { // Cases 3 and 4
- exponentAdjust = -4*( rightDigits - signifLength + 1);
- }
-
- // If the significand is zero, the exponent doesn't
- // matter; return a properly signed zero.
-
- if (signifLength == 0) { // Only zeros in input
- return loadDouble(sign * 0.0);
- }
- }
-
- // Extract Exponent
- /*
- * Use an int to read in the exponent value; this should
- * provide more than sufficient range for non-contrived
- * inputs. If reading the exponent in as an int does
- * overflow, examine the sign of the exponent and
- * significand to determine what to do.
- */
- String group8 = m.group(8);
- boolean positiveExponent = ( group8 == null ) || group8.equals("+");
- long unsignedRawExponent;
- try {
- unsignedRawExponent = Integer.parseInt(m.group(9));
- }
- catch (NumberFormatException e) {
- // At this point, we know the exponent is
- // syntactically well-formed as a sequence of
- // digits. Therefore, if an NumberFormatException
- // is thrown, it must be due to overflowing int's
- // range. Also, at this point, we have already
- // checked for a zero significand. Thus the signs
- // of the exponent and significand determine the
- // final result:
- //
- // significand
- // + -
- // exponent + +infinity -infinity
- // - +0.0 -0.0
- return loadDouble(sign * (positiveExponent ?
- Double.POSITIVE_INFINITY : 0.0));
- }
-
- long rawExponent =
- (positiveExponent ? 1L : -1L) * // exponent sign
- unsignedRawExponent; // exponent magnitude
-
- // Calculate partially adjusted exponent
- long exponent = rawExponent + exponentAdjust ;
-
- // Starting copying non-zero bits into proper position in
- // a long; copy explicit bit too; this will be masked
- // later for normal values.
-
- boolean round = false;
- boolean sticky = false;
- int bitsCopied=0;
- int nextShift=0;
- long significand=0L;
- // First iteration is different, since we only copy
- // from the leading significand bit; one more exponent
- // adjust will be needed...
-
- // IMPORTANT: make leadingDigit a long to avoid
- // surprising shift semantics!
- long leadingDigit = getHexDigit(significandString, 0);
-
- /*
- * Left shift the leading digit (53 - (bit position of
- * leading 1 in digit)); this sets the top bit of the
- * significand to 1. The nextShift value is adjusted
- * to take into account the number of bit positions of
- * the leadingDigit actually used. Finally, the
- * exponent is adjusted to normalize the significand
- * as a binary value, not just a hex value.
- */
- if (leadingDigit == 1) {
- significand |= leadingDigit << 52;
- nextShift = 52 - 4;
- /* exponent += 0 */ }
- else if (leadingDigit <= 3) { // [2, 3]
- significand |= leadingDigit << 51;
- nextShift = 52 - 5;
- exponent += 1;
- }
- else if (leadingDigit <= 7) { // [4, 7]
- significand |= leadingDigit << 50;
- nextShift = 52 - 6;
- exponent += 2;
- }
- else if (leadingDigit <= 15) { // [8, f]
- significand |= leadingDigit << 49;
- nextShift = 52 - 7;
- exponent += 3;
- } else {
- throw new AssertionError("Result from digit conversion too large!");
- }
- // The preceding if-else could be replaced by a single
- // code block based on the high-order bit set in
- // leadingDigit. Given leadingOnePosition,
-
- // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
- // nextShift = 52 - (3 + leadingOnePosition);
- // exponent += (leadingOnePosition-1);
-
-
- /*
- * Now the exponent variable is equal to the normalized
- * binary exponent. Code below will make representation
- * adjustments if the exponent is incremented after
- * rounding (includes overflows to infinity) or if the
- * result is subnormal.
- */
-
- // Copy digit into significand until the significand can't
- // hold another full hex digit or there are no more input
- // hex digits.
- int i = 0;
- for(i = 1;
- i < signifLength && nextShift >= 0;
- i++) {
- long currentDigit = getHexDigit(significandString, i);
- significand |= (currentDigit << nextShift);
- nextShift-=4;
- }
-
- // After the above loop, the bulk of the string is copied.
- // Now, we must copy any partial hex digits into the
- // significand AND compute the round bit and start computing
- // sticky bit.
-
- if ( i < signifLength ) { // at least one hex input digit exists
- long currentDigit = getHexDigit(significandString, i);
-
- // from nextShift, figure out how many bits need
- // to be copied, if any
- switch(nextShift) { // must be negative
- case -1:
- // three bits need to be copied in; can
- // set round bit
- significand |= ((currentDigit & 0xEL) >> 1);
- round = (currentDigit & 0x1L) != 0L;
- break;
-
- case -2:
- // two bits need to be copied in; can
- // set round and start sticky
- significand |= ((currentDigit & 0xCL) >> 2);
- round = (currentDigit &0x2L) != 0L;
- sticky = (currentDigit & 0x1L) != 0;
- break;
-
- case -3:
- // one bit needs to be copied in
- significand |= ((currentDigit & 0x8L)>>3);
- // Now set round and start sticky, if possible
- round = (currentDigit &0x4L) != 0L;
- sticky = (currentDigit & 0x3L) != 0;
- break;
-
- case -4:
- // all bits copied into significand; set
- // round and start sticky
- round = ((currentDigit & 0x8L) != 0); // is top bit set?
- // nonzeros in three low order bits?
- sticky = (currentDigit & 0x7L) != 0;
- break;
-
- default:
- throw new AssertionError("Unexpected shift distance remainder.");
- // break;
- }
-
- // Round is set; sticky might be set.
-
- // For the sticky bit, it suffices to check the
- // current digit and test for any nonzero digits in
- // the remaining unprocessed input.
- i++;
- while(i < signifLength && !sticky) {
- currentDigit = getHexDigit(significandString,i);
- sticky = sticky || (currentDigit != 0);
- i++;
- }
-
- }
- // else all of string was seen, round and sticky are
- // correct as false.
-
-
- // Check for overflow and update exponent accordingly.
-
- if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
- // overflow to properly signed infinity
- return loadDouble(sign * Double.POSITIVE_INFINITY);
- } else { // Finite return value
- if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
- exponent >= DoubleConsts.MIN_EXPONENT) {
-
- // The result returned in this block cannot be a
- // zero or subnormal; however after the
- // significand is adjusted from rounding, we could
- // still overflow in infinity.
-
- // AND exponent bits into significand; if the
- // significand is incremented and overflows from
- // rounding, this combination will update the
- // exponent correctly, even in the case of
- // Double.MAX_VALUE overflowing to infinity.
-
- significand = (( ((long)exponent +
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
- } else { // Subnormal or zero
- // (exponent < DoubleConsts.MIN_EXPONENT)
-
- if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
- // No way to round back to nonzero value
- // regardless of significand if the exponent is
- // less than -1075.
- return loadDouble(sign * 0.0);
- } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
- /*
- * Find bit position to round to; recompute
- * round and sticky bits, and shift
- * significand right appropriately.
- */
-
- sticky = sticky || round;
- round = false;
-
- // Number of bits of significand to preserve is
- // exponent - abs_min_exp +1
- // check:
- // -1075 +1074 + 1 = 0
- // -1023 +1074 + 1 = 52
-
- int bitsDiscarded = 53 -
- ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
- assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
- // What to do here:
- // First, isolate the new round bit
- round = (significand & (1L << (bitsDiscarded -1))) != 0L;
- if (bitsDiscarded > 1) {
- // create mask to update sticky bits; low
- // order bitsDiscarded bits should be 1
- long mask = ~((~0L) << (bitsDiscarded -1));
- sticky = sticky || ((significand & mask) != 0L ) ;
- }
-
- // Now, discard the bits
- significand = significand >> bitsDiscarded;
-
- significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp.
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
- }
- }
-
- // The significand variable now contains the currently
- // appropriate exponent bits too.
-
- /*
- * Determine if significand should be incremented;
- * making this determination depends on the least
- * significant bit and the round and sticky bits.
- *
- * Round to nearest even rounding table, adapted from
- * table 4.7 in "Computer Arithmetic" by IsraelKoren.
- * The digit to the left of the "decimal" point is the
- * least significant bit, the digits to the right of
- * the point are the round and sticky bits
- *
- * Number Round(x)
- * x0.00 x0.
- * x0.01 x0.
- * x0.10 x0.
- * x0.11 x1. = x0. +1
- * x1.00 x1.
- * x1.01 x1.
- * x1.10 x1. + 1
- * x1.11 x1. + 1
- */
- boolean incremented = false;
- boolean leastZero = ((significand & 1L) == 0L);
- if( ( leastZero && round && sticky ) ||
- ((!leastZero) && round )) {
- incremented = true;
- significand++;
- }
-
- loadDouble(FpUtils.rawCopySign(
- Double.longBitsToDouble(significand),
- sign));
-
- /*
- * Set roundingDir variable field of fd properly so
- * that the input string can be properly rounded to a
- * float value. There are two cases to consider:
- *
- * 1. rounding to double discards sticky bit
- * information that would change the result of a float
- * rounding (near halfway case between two floats)
- *
- * 2. rounding to double rounds up when rounding up
- * would not occur when rounding to float.
- *
- * For former case only needs to be considered when
- * the bits rounded away when casting to float are all
- * zero; otherwise, float round bit is properly set
- * and sticky will already be true.
- *
- * The lower exponent bound for the code below is the
- * minimum (normalized) subnormal exponent - 1 since a
- * value with that exponent can round up to the
- * minimum subnormal value and the sticky bit
- * information must be preserved (i.e. case 1).
- */
- if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
- (exponent <= FloatConsts.MAX_EXPONENT ) ){
- // Outside above exponent range, the float value
- // will be zero or infinity.
-
- /*
- * If the low-order 28 bits of a rounded double
- * significand are 0, the double could be a
- * half-way case for a rounding to float. If the
- * double value is a half-way case, the double
- * significand may have to be modified to round
- * the the right float value (see the stickyRound
- * method). If the rounding to double has lost
- * what would be float sticky bit information, the
- * double significand must be incremented. If the
- * double value's significand was itself
- * incremented, the float value may end up too
- * large so the increment should be undone.
- */
- if ((significand & 0xfffffffL) == 0x0L) {
- // For negative values, the sign of the
- // roundDir is the same as for positive values
- // since adding 1 increasing the significand's
- // magnitude and subtracting 1 decreases the
- // significand's magnitude. If neither round
- // nor sticky is true, the double value is
- // exact and no adjustment is required for a
- // proper float rounding.
- if( round || sticky) {
- if (leastZero) { // prerounding lsb is 0
- // If round and sticky were both true,
- // and the least significant
- // significand bit were 0, the rounded
- // significand would not have its
- // low-order bits be zero. Therefore,
- // we only need to adjust the
- // significand if round XOR sticky is
- // true.
- if (round ^ sticky) {
- this.roundDir = 1;
- }
- }
- else { // prerounding lsb is 1
- // If the prerounding lsb is 1 and the
- // resulting significand has its
- // low-order bits zero, the significand
- // was incremented. Here, we undo the
- // increment, which will ensure the
- // right guard and sticky bits for the
- // float rounding.
- if (round)
- this.roundDir = -1;
- }
- }
- }
- }
-
- this.fromHex = true;
- return this;
- }
- }
- }
-
- /**
- * Return <code>s</code> with any leading zeros removed.
- */
- static String stripLeadingZeros(String s) {
- return s.replaceFirst("^0+", "");
- }
-
- /**
- * Extract a hexadecimal digit from position <code>position</code>
- * of string <code>s</code>.
- */
- static int getHexDigit(String s, int position) {
- int value = Character.digit(s.charAt(position), 16);
- if (value <= -1 || value >= 16) {
- throw new AssertionError("Unexpected failure of digit conversion of " +
- s.charAt(position));
- }
- return value;
- }
-
-
-}
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 94b949e..ea5a642 100755
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -34,6 +34,8 @@
import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
+import java.util.Objects;
+import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -42,23 +44,23 @@
import libcore.util.EmptyArray;
/**
- * The <code>String</code> class represents character strings. All
- * string literals in Java programs, such as <code>"abc"</code>, are
+ * The {@code String} class represents character strings. All
+ * string literals in Java programs, such as {@code "abc"}, are
* implemented as instances of this class.
* <p>
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>
* is equivalent to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
* </pre></blockquote><p>
* Here are some more examples of how strings can be used:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* System.out.println("abc");
* String cde = "cde";
* System.out.println("abc" + cde);
@@ -66,7 +68,7 @@
* String d = cde.substring(1, 2);
* </pre></blockquote>
* <p>
- * The class <code>String</code> includes methods for examining
+ * The class {@code String} includes methods for examining
* individual characters of the sequence, for comparing strings, for
* searching strings, for extracting substrings, and for creating a
* copy of a string with all characters translated to uppercase or to
@@ -76,10 +78,10 @@
* The Java language provides special support for the string
* concatenation operator ( + ), and for conversion of
* other objects to strings. String concatenation is implemented
- * through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
- * class and its <code>append</code> method.
+ * through the {@code StringBuilder}(or {@code StringBuffer})
+ * class and its {@code append} method.
* String conversions are implemented through the method
- * <code>toString</code>, defined by <code>Object</code> and
+ * {@code toString}, defined by {@code Object} and
* inherited by all classes in Java. For additional information on
* string concatenation and conversion, see Gosling, Joy, and Steele,
* <i>The Java Language Specification</i>.
@@ -88,16 +90,16 @@
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
*
- * <p>A <code>String</code> represents a string in the UTF-16 format
+ * <p>A {@code String} represents a string in the UTF-16 format
* in which <em>supplementary characters</em> are represented by <em>surrogate
* pairs</em> (see the section <a href="Character.html#unicode">Unicode
- * Character Representations</a> in the <code>Character</code> class for
+ * Character Representations</a> in the {@code Character} class for
* more information).
- * Index values refer to <code>char</code> code units, so a supplementary
- * character uses two positions in a <code>String</code>.
- * <p>The <code>String</code> class provides methods for dealing with
+ * Index values refer to {@code char} code units, so a supplementary
+ * character uses two positions in a {@code String}.
+ * <p>The {@code String} class provides methods for dealing with
* Unicode code points (i.e., characters), in addition to those for
- * dealing with Unicode code units (i.e., <code>char</code> values).
+ * dealing with Unicode code units (i.e., {@code char} values).
*
* @author Lee Boynton
* @author Arthur van Hoff
@@ -113,7 +115,7 @@
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
- // The associated character storage is managed by the runtime. We only
+ // dThe associated character storage is managed by the runtime. We only
// keep track of the length here.
//
// private final char value[];
@@ -128,17 +130,12 @@
/**
* Class String is special cased within the Serialization Stream Protocol.
*
- * A String instance is written initially into an ObjectOutputStream in the
- * following format:
- * <pre>
- * <code>TC_STRING</code> (utf String)
- * </pre>
- * The String is written by method <code>DataOutput.writeUTF</code>.
- * A new handle is generated to refer to all future references to the
- * string instance within the stream.
+ * A String instance is written into an ObjectOutputStream according to
+ * <a href="{@docRoot}/../platform/serialization/spec/output.html">
+ * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
- new ObjectStreamField[0];
+ new ObjectStreamField[0];
/**
* Initializes a newly created {@code String} object so that it represents
@@ -542,10 +539,10 @@
}
/**
- * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
+ * Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
*
- * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise
- * <tt>false</tt>
+ * @return {@code true} if {@link #length()} is {@code 0}, otherwise
+ * {@code false}
*
* @since 1.6
*/
@@ -554,20 +551,20 @@
}
/**
- * Returns the <code>char</code> value at the
- * specified index. An index ranges from <code>0</code> to
- * <code>length() - 1</code>. The first <code>char</code> value of the sequence
- * is at index <code>0</code>, the next at index <code>1</code>,
+ * Returns the {@code char} value at the
+ * specified index. An index ranges from {@code 0} to
+ * {@code length() - 1}. The first {@code char} value of the sequence
+ * is at index {@code 0}, the next at index {@code 1},
* and so on, as for array indexing.
*
- * <p>If the <code>char</code> value specified by the index is a
+ * <p>If the {@code char} value specified by the index is a
* <a href="Character.html#unicode">surrogate</a>, the surrogate
* value is returned.
*
- * @param index the index of the <code>char</code> value.
- * @return the <code>char</code> value at the specified index of this string.
- * The first <code>char</code> value is at index <code>0</code>.
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * @param index the index of the {@code char} value.
+ * @return the {@code char} value at the specified index of this string.
+ * The first {@code char} value is at index {@code 0}.
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* string.
*/
@@ -577,22 +574,22 @@
/**
* Returns the character (Unicode code point) at the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>0</code> to
- * {@link #length()}<code> - 1</code>.
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 0} to
+ * {@link #length()}{@code - 1}.
*
- * <p> If the <code>char</code> value specified at the given index
+ * <p> If the {@code char} value specified at the given index
* is in the high-surrogate range, the following index is less
- * than the length of this <code>String</code>, and the
- * <code>char</code> value at the following index is in the
+ * than the length of this {@code String}, and the
+ * {@code char} value at the following index is in the
* low-surrogate range, then the supplementary code point
* corresponding to this surrogate pair is returned. Otherwise,
- * the <code>char</code> value at the given index is returned.
+ * the {@code char} value at the given index is returned.
*
- * @param index the index to the <code>char</code> values
+ * @param index the index to the {@code char} values
* @return the code point value of the character at the
- * <code>index</code>
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * {@code index}
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* string.
* @since 1.5
@@ -606,22 +603,22 @@
/**
* Returns the character (Unicode code point) before the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>1</code> to {@link
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 1} to {@link
* CharSequence#length() length}.
*
- * <p> If the <code>char</code> value at <code>(index - 1)</code>
- * is in the low-surrogate range, <code>(index - 2)</code> is not
- * negative, and the <code>char</code> value at <code>(index -
- * 2)</code> is in the high-surrogate range, then the
+ * <p> If the {@code char} value at {@code (index - 1)}
+ * is in the low-surrogate range, {@code (index - 2)} is not
+ * negative, and the {@code char} value at {@code (index -
+ * 2)} is in the high-surrogate range, then the
* supplementary code point value of the surrogate pair is
- * returned. If the <code>char</code> value at <code>index -
- * 1</code> is an unpaired low-surrogate or a high-surrogate, the
+ * returned. If the {@code char} value at {@code index -
+ * 1} is an unpaired low-surrogate or a high-surrogate, the
* surrogate value is returned.
*
* @param index the index following the code point that should be returned
* @return the Unicode code point value before the given index.
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is less than 1 or greater than the length
* of this string.
* @since 1.5
@@ -636,23 +633,23 @@
/**
* Returns the number of Unicode code points in the specified text
- * range of this <code>String</code>. The text range begins at the
- * specified <code>beginIndex</code> and extends to the
- * <code>char</code> at index <code>endIndex - 1</code>. Thus the
- * length (in <code>char</code>s) of the text range is
- * <code>endIndex-beginIndex</code>. Unpaired surrogates within
+ * range of this {@code String}. The text range begins at the
+ * specified {@code beginIndex} and extends to the
+ * {@code char} at index {@code endIndex - 1}. Thus the
+ * length (in {@code char}s) of the text range is
+ * {@code endIndex-beginIndex}. Unpaired surrogates within
* the text range count as one code point each.
*
- * @param beginIndex the index to the first <code>char</code> of
+ * @param beginIndex the index to the first {@code char} of
* the text range.
- * @param endIndex the index after the last <code>char</code> of
+ * @param endIndex the index after the last {@code char} of
* the text range.
* @return the number of Unicode code points in the specified text
* range
* @exception IndexOutOfBoundsException if the
- * <code>beginIndex</code> is negative, or <code>endIndex</code>
- * is larger than the length of this <code>String</code>, or
- * <code>beginIndex</code> is larger than <code>endIndex</code>.
+ * {@code beginIndex} is negative, or {@code endIndex}
+ * is larger than the length of this {@code String}, or
+ * {@code beginIndex} is larger than {@code endIndex}.
* @since 1.5
*/
public int codePointCount(int beginIndex, int endIndex) {
@@ -663,23 +660,23 @@
}
/**
- * Returns the index within this <code>String</code> that is
- * offset from the given <code>index</code> by
- * <code>codePointOffset</code> code points. Unpaired surrogates
- * within the text range given by <code>index</code> and
- * <code>codePointOffset</code> count as one code point each.
+ * Returns the index within this {@code String} that is
+ * offset from the given {@code index} by
+ * {@code codePointOffset} code points. Unpaired surrogates
+ * within the text range given by {@code index} and
+ * {@code codePointOffset} count as one code point each.
*
* @param index the index to be offset
* @param codePointOffset the offset in code points
- * @return the index within this <code>String</code>
- * @exception IndexOutOfBoundsException if <code>index</code>
+ * @return the index within this {@code String}
+ * @exception IndexOutOfBoundsException if {@code index}
* is negative or larger then the length of this
- * <code>String</code>, or if <code>codePointOffset</code> is positive
- * and the substring starting with <code>index</code> has fewer
- * than <code>codePointOffset</code> code points,
- * or if <code>codePointOffset</code> is negative and the substring
- * before <code>index</code> has fewer than the absolute value
- * of <code>codePointOffset</code> code points.
+ * {@code String}, or if {@code codePointOffset} is positive
+ * and the substring starting with {@code index} has fewer
+ * than {@code codePointOffset} code points,
+ * or if {@code codePointOffset} is negative and the substring
+ * before {@code index} has fewer than the absolute value
+ * of {@code codePointOffset} code points.
* @since 1.5
*/
public int offsetByCodePoints(int index, int codePointOffset) {
@@ -690,17 +687,25 @@
}
/**
+ * Copy characters from this string into dst starting at dstBegin.
+ * This method doesn't perform any range checking.
+ */
+ void getChars(char dst[], int dstBegin) {
+ getCharsNoCheck(0, count, dst, dstBegin);
+ }
+
+ /**
* Copies characters from this string into the destination character
* array.
* <p>
- * The first character to be copied is at index <code>srcBegin</code>;
- * the last character to be copied is at index <code>srcEnd-1</code>
+ * The first character to be copied is at index {@code srcBegin};
+ * the last character to be copied is at index {@code srcEnd-1}
* (thus the total number of characters to be copied is
- * <code>srcEnd-srcBegin</code>). The characters are copied into the
- * subarray of <code>dst</code> starting at index <code>dstBegin</code>
+ * {@code srcEnd-srcBegin}). The characters are copied into the
+ * subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
- * <p><blockquote><pre>
- * dstbegin + (srcEnd-srcBegin) - 1
+ * <blockquote><pre>
+ * dstBegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
* @param srcBegin index of the first character in the string
@@ -711,13 +716,13 @@
* @param dstBegin the start offset in the destination array.
* @exception IndexOutOfBoundsException If any of the following
* is true:
- * <ul><li><code>srcBegin</code> is negative.
- * <li><code>srcBegin</code> is greater than <code>srcEnd</code>
- * <li><code>srcEnd</code> is greater than the length of this
+ * <ul><li>{@code srcBegin} is negative.
+ * <li>{@code srcBegin} is greater than {@code srcEnd}
+ * <li>{@code srcEnd} is greater than the length of this
* string
- * <li><code>dstBegin</code> is negative
- * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
- * <code>dst.length</code></ul>
+ * <li>{@code dstBegin} is negative
+ * <li>{@code dstBegin+(srcEnd-srcBegin)} is larger than
+ * {@code dst.length}</ul>
*/
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (dst == null) {
@@ -775,7 +780,7 @@
* dst} starting at index {@code dstBegin} and ending at index:
*
* <blockquote><pre>
- * dstbegin + (srcEnd-srcBegin) - 1
+ * dstBegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
* @deprecated This method does not properly convert characters into
@@ -848,6 +853,7 @@
*/
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
+ if (charsetName == null) throw new NullPointerException();
return getBytes(Charset.forNameUEE(charsetName));
}
@@ -943,7 +949,8 @@
/**
* Compares this string to the specified {@code StringBuffer}. The result
* is {@code true} if and only if this {@code String} represents the same
- * sequence of characters as the specified {@code StringBuffer}.
+ * sequence of characters as the specified {@code StringBuffer}. This method
+ * synchronizes on the {@code StringBuffer}.
*
* @param sb
* The {@code StringBuffer} to compare this {@code String} against
@@ -955,15 +962,29 @@
* @since 1.4
*/
public boolean contentEquals(StringBuffer sb) {
- synchronized (sb) {
- return contentEquals((CharSequence) sb);
+ return contentEquals((CharSequence)sb);
+ }
+
+ private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
+ char v2[] = sb.getValue();
+ int n = count;
+ if (n != sb.length()) {
+ return false;
}
+ for (int i = 0; i < n; i++) {
+ if (charAt(i) != v2[i]) {
+ return false;
+ }
+ }
+ return true;
}
/**
- * Compares this string to the specified {@code CharSequence}. The result
- * is {@code true} if and only if this {@code String} represents the same
- * sequence of char values as the specified sequence.
+ * Compares this string to the specified {@code CharSequence}. The
+ * result is {@code true} if and only if this {@code String} represents the
+ * same sequence of char values as the specified sequence. Note that if the
+ * {@code CharSequence} is a {@code StringBuffer} then the method
+ * synchronizes on it.
*
* @param cs
* The sequence to compare this {@code String} against
@@ -975,30 +996,29 @@
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
- if (count != cs.length())
- return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
- char v2[] = ((AbstractStringBuilder) cs).getValue();
- int i = 0;
- int n = count;
- while (n-- != 0) {
- if (charAt(i) != v2[i])
- return false;
- i++;
+ if (cs instanceof StringBuffer) {
+ synchronized(cs) {
+ return nonSyncContentEquals((AbstractStringBuilder)cs);
+ }
+ } else {
+ return nonSyncContentEquals((AbstractStringBuilder)cs);
}
- return true;
}
// Argument is a String
- if (cs.equals(this))
- return true;
+ if (cs instanceof String) {
+ return equals(cs);
+ }
// Argument is a generic CharSequence
- int i = 0;
int n = count;
- while (n-- != 0) {
- if (charAt(i) != cs.charAt(i))
+ if (n != cs.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
+ if (charAt(i) != cs.charAt(i)) {
return false;
- i++;
+ }
}
return true;
}
@@ -1042,14 +1062,14 @@
* Compares two strings lexicographically.
* The comparison is based on the Unicode value of each character in
* the strings. The character sequence represented by this
- * <code>String</code> object is compared lexicographically to the
+ * {@code String} object is compared lexicographically to the
* character sequence represented by the argument string. The result is
- * a negative integer if this <code>String</code> object
+ * a negative integer if this {@code String} object
* lexicographically precedes the argument string. The result is a
- * positive integer if this <code>String</code> object lexicographically
+ * positive integer if this {@code String} object lexicographically
* follows the argument string. The result is zero if the strings
- * are equal; <code>compareTo</code> returns <code>0</code> exactly when
- * the {@link #equals(Object)} method would return <code>true</code>.
+ * are equal; {@code compareTo} returns {@code 0} exactly when
+ * the {@link #equals(Object)} method would return {@code true}.
* <p>
* This is the definition of lexicographic ordering. If two strings are
* different, then either they have different characters at some index
@@ -1058,32 +1078,32 @@
* positions, let <i>k</i> be the smallest such index; then the string
* whose character at position <i>k</i> has the smaller value, as
* determined by using the < operator, lexicographically precedes the
- * other string. In this case, <code>compareTo</code> returns the
- * difference of the two character values at position <code>k</code> in
+ * other string. In this case, {@code compareTo} returns the
+ * difference of the two character values at position {@code k} in
* the two string -- that is, the value:
* <blockquote><pre>
* this.charAt(k)-anotherString.charAt(k)
* </pre></blockquote>
* If there is no index position at which they differ, then the shorter
* string lexicographically precedes the longer string. In this case,
- * <code>compareTo</code> returns the difference of the lengths of the
+ * {@code compareTo} returns the difference of the lengths of the
* strings -- that is, the value:
* <blockquote><pre>
* this.length()-anotherString.length()
* </pre></blockquote>
*
- * @param anotherString the <code>String</code> to be compared.
- * @return the value <code>0</code> if the argument string is equal to
- * this string; a value less than <code>0</code> if this string
+ * @param anotherString the {@code String} to be compared.
+ * @return the value {@code 0} if the argument string is equal to
+ * this string; a value less than {@code 0} if this string
* is lexicographically less than the string argument; and a
- * value greater than <code>0</code> if this string is
+ * value greater than {@code 0} if this string is
* lexicographically greater than the string argument.
*/
public native int compareTo(String anotherString);
/**
- * A Comparator that orders <code>String</code> objects as by
- * <code>compareToIgnoreCase</code>. This comparator is serializable.
+ * A Comparator that orders {@code String} objects as by
+ * {@code compareToIgnoreCase}. This comparator is serializable.
* <p>
* Note that this Comparator does <em>not</em> take locale into account,
* and will result in an unsatisfactory ordering for certain locales.
@@ -1122,14 +1142,17 @@
}
return n1 - n2;
}
+
+ /** Replaces the de-serialized object. */
+ private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}
/**
* Compares two strings lexicographically, ignoring case
* differences. This method returns an integer whose sign is that of
- * calling <code>compareTo</code> with normalized versions of the strings
+ * calling {@code compareTo} with normalized versions of the strings
* where case differences have been eliminated by calling
- * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on
+ * {@code Character.toLowerCase(Character.toUpperCase(character))} on
* each character.
* <p>
* Note that this method does <em>not</em> take locale into account,
@@ -1137,7 +1160,7 @@
* The java.text package provides <em>collators</em> to allow
* locale-sensitive ordering.
*
- * @param str the <code>String</code> to be compared.
+ * @param str the {@code String} to be compared.
* @return a negative integer, zero, or a positive integer as the
* specified String is greater than, equal to, or less
* than this String, ignoring case considerations.
@@ -1151,23 +1174,24 @@
/**
* Tests if two string regions are equal.
* <p>
- * A substring of this <tt>String</tt> object is compared to a substring
+ * A substring of this {@code String} object is compared to a substring
* of the argument other. The result is true if these substrings
* represent identical character sequences. The substring of this
- * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
- * and has length <tt>len</tt>. The substring of other to be compared
- * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
- * result is <tt>false</tt> if and only if at least one of the following
+ * {@code String} object to be compared begins at index {@code toffset}
+ * and has length {@code len}. The substring of other to be compared
+ * begins at index {@code ooffset} and has length {@code len}. The
+ * result is {@code false} if and only if at least one of the following
* is true:
- * <ul><li><tt>toffset</tt> is negative.
- * <li><tt>ooffset</tt> is negative.
- * <li><tt>toffset+len</tt> is greater than the length of this
- * <tt>String</tt> object.
- * <li><tt>ooffset+len</tt> is greater than the length of the other
+ * <ul><li>{@code toffset} is negative.
+ * <li>{@code ooffset} is negative.
+ * <li>{@code toffset+len} is greater than the length of this
+ * {@code String} object.
+ * <li>{@code ooffset+len} is greater than the length of the other
* argument.
- * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
+ * <li>There is some nonnegative integer <i>k</i> less than {@code len}
* such that:
- * <tt>this.charAt(toffset+<i>k</i>) != other.charAt(ooffset+<i>k</i>)</tt>
+ * {@code this.charAt(toffset + }<i>k</i>{@code ) != other.charAt(ooffset + }
+ * <i>k</i>{@code )}
* </ul>
*
* @param toffset the starting offset of the subregion in this string.
@@ -1175,9 +1199,9 @@
* @param ooffset the starting offset of the subregion in the string
* argument.
* @param len the number of characters to compare.
- * @return <code>true</code> if the specified subregion of this string
+ * @return {@code true} if the specified subregion of this string
* exactly matches the specified subregion of the string argument;
- * <code>false</code> otherwise.
+ * {@code false} otherwise.
*/
public boolean regionMatches(int toffset, String other, int ooffset,
int len) {
@@ -1200,28 +1224,28 @@
/**
* Tests if two string regions are equal.
* <p>
- * A substring of this <tt>String</tt> object is compared to a substring
- * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
+ * A substring of this {@code String} object is compared to a substring
+ * of the argument {@code other}. The result is {@code true} if these
* substrings represent character sequences that are the same, ignoring
- * case if and only if <tt>ignoreCase</tt> is true. The substring of
- * this <tt>String</tt> object to be compared begins at index
- * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
- * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
- * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
+ * case if and only if {@code ignoreCase} is true. The substring of
+ * this {@code String} object to be compared begins at index
+ * {@code toffset} and has length {@code len}. The substring of
+ * {@code other} to be compared begins at index {@code ooffset} and
+ * has length {@code len}. The result is {@code false} if and only if
* at least one of the following is true:
- * <ul><li><tt>toffset</tt> is negative.
- * <li><tt>ooffset</tt> is negative.
- * <li><tt>toffset+len</tt> is greater than the length of this
- * <tt>String</tt> object.
- * <li><tt>ooffset+len</tt> is greater than the length of the other
+ * <ul><li>{@code toffset} is negative.
+ * <li>{@code ooffset} is negative.
+ * <li>{@code toffset+len} is greater than the length of this
+ * {@code String} object.
+ * <li>{@code ooffset+len} is greater than the length of the other
* argument.
- * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative
- * integer <i>k</i> less than <tt>len</tt> such that:
+ * <li>{@code ignoreCase} is {@code false} and there is some nonnegative
+ * integer <i>k</i> less than {@code len} such that:
* <blockquote><pre>
* this.charAt(toffset+k) != other.charAt(ooffset+k)
* </pre></blockquote>
- * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
- * integer <i>k</i> less than <tt>len</tt> such that:
+ * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
+ * integer <i>k</i> less than {@code len} such that:
* <blockquote><pre>
* Character.toLowerCase(this.charAt(toffset+k)) !=
Character.toLowerCase(other.charAt(ooffset+k))
@@ -1233,7 +1257,7 @@
* </pre></blockquote>
* </ul>
*
- * @param ignoreCase if <code>true</code>, ignore case when comparing
+ * @param ignoreCase if {@code true}, ignore case when comparing
* characters.
* @param toffset the starting offset of the subregion in this
* string.
@@ -1241,10 +1265,10 @@
* @param ooffset the starting offset of the subregion in the string
* argument.
* @param len the number of characters to compare.
- * @return <code>true</code> if the specified subregion of this string
+ * @return {@code true} if the specified subregion of this string
* matches the specified subregion of the string argument;
- * <code>false</code> otherwise. Whether the matching is exact
- * or case insensitive depends on the <code>ignoreCase</code>
+ * {@code false} otherwise. Whether the matching is exact
+ * or case insensitive depends on the {@code ignoreCase}
* argument.
*/
public boolean regionMatches(boolean ignoreCase, int toffset,
@@ -1292,12 +1316,12 @@
*
* @param prefix the prefix.
* @param toffset where to begin looking in this string.
- * @return <code>true</code> if the character sequence represented by the
+ * @return {@code true} if the character sequence represented by the
* argument is a prefix of the substring of this object starting
- * at index <code>toffset</code>; <code>false</code> otherwise.
- * The result is <code>false</code> if <code>toffset</code> is
+ * at index {@code toffset}; {@code false} otherwise.
+ * The result is {@code false} if {@code toffset} is
* negative or greater than the length of this
- * <code>String</code> object; otherwise the result is the same
+ * {@code String} object; otherwise the result is the same
* as the result of the expression
* <pre>
* this.substring(toffset).startsWith(prefix)
@@ -1323,12 +1347,12 @@
* Tests if this string starts with the specified prefix.
*
* @param prefix the prefix.
- * @return <code>true</code> if the character sequence represented by the
+ * @return {@code true} if the character sequence represented by the
* argument is a prefix of the character sequence represented by
- * this string; <code>false</code> otherwise.
- * Note also that <code>true</code> will be returned if the
+ * this string; {@code false} otherwise.
+ * Note also that {@code true} will be returned if the
* argument is an empty string or is equal to this
- * <code>String</code> object as determined by the
+ * {@code String} object as determined by the
* {@link #equals(Object)} method.
* @since 1. 0
*/
@@ -1340,11 +1364,11 @@
* Tests if this string ends with the specified suffix.
*
* @param suffix the suffix.
- * @return <code>true</code> if the character sequence represented by the
+ * @return {@code true} if the character sequence represented by the
* argument is a suffix of the character sequence represented by
- * this object; <code>false</code> otherwise. Note that the
- * result will be <code>true</code> if the argument is the
- * empty string or is equal to this <code>String</code> object
+ * this object; {@code false} otherwise. Note that the
+ * result will be {@code true} if the argument is the
+ * empty string or is equal to this {@code String} object
* as determined by the {@link #equals(Object)} method.
*/
public boolean endsWith(String suffix) {
@@ -1353,13 +1377,13 @@
/**
* Returns a hash code for this string. The hash code for a
- * <code>String</code> object is computed as
+ * {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
- * using <code>int</code> arithmetic, where <code>s[i]</code> is the
- * <i>i</i>th character of the string, <code>n</code> is the length of
- * the string, and <code>^</code> indicates exponentiation.
+ * using {@code int} arithmetic, where {@code s[i]} is the
+ * <i>i</i>th character of the string, {@code n} is the length of
+ * the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
@@ -1378,26 +1402,26 @@
/**
* Returns the index within this string of the first occurrence of
* the specified character. If a character with value
- * <code>ch</code> occurs in the character sequence represented by
- * this <code>String</code> object, then the index (in Unicode
+ * {@code ch} occurs in the character sequence represented by
+ * this {@code String} object, then the index (in Unicode
* code units) of the first such occurrence is returned. For
- * values of <code>ch</code> in the range from 0 to 0xFFFF
+ * values of {@code ch} in the range from 0 to 0xFFFF
* (inclusive), this is the smallest value <i>k</i> such that:
* <blockquote><pre>
* this.charAt(<i>k</i>) == ch
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* smallest value <i>k</i> such that:
* <blockquote><pre>
* this.codePointAt(<i>k</i>) == ch
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string, then <code>-1</code> is returned.
+ * string, then {@code -1} is returned.
*
* @param ch a character (Unicode code point).
* @return the index of the first occurrence of the character in the
* character sequence represented by this object, or
- * <code>-1</code> if the character does not occur.
+ * {@code -1} if the character does not occur.
*/
public int indexOf(int ch) {
return indexOf(ch, 0);
@@ -1407,39 +1431,39 @@
* Returns the index within this string of the first occurrence of the
* specified character, starting the search at the specified index.
* <p>
- * If a character with value <code>ch</code> occurs in the
- * character sequence represented by this <code>String</code>
- * object at an index no smaller than <code>fromIndex</code>, then
+ * If a character with value {@code ch} occurs in the
+ * character sequence represented by this {@code String}
+ * object at an index no smaller than {@code fromIndex}, then
* the index of the first such occurrence is returned. For values
- * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive),
+ * of {@code ch} in the range from 0 to 0xFFFF (inclusive),
* this is the smallest value <i>k</i> such that:
* <blockquote><pre>
- * (this.charAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex)
+ * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> >= fromIndex)
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* smallest value <i>k</i> such that:
* <blockquote><pre>
- * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex)
+ * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> >= fromIndex)
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string at or after position <code>fromIndex</code>, then
- * <code>-1</code> is returned.
+ * string at or after position {@code fromIndex}, then
+ * {@code -1} is returned.
*
* <p>
- * There is no restriction on the value of <code>fromIndex</code>. If it
+ * There is no restriction on the value of {@code fromIndex}. If it
* is negative, it has the same effect as if it were zero: this entire
* string may be searched. If it is greater than the length of this
* string, it has the same effect as if it were equal to the length of
- * this string: <code>-1</code> is returned.
+ * this string: {@code -1} is returned.
*
- * <p>All indices are specified in <code>char</code> values
+ * <p>All indices are specified in {@code char} values
* (Unicode code units).
*
* @param ch a character (Unicode code point).
* @param fromIndex the index to start the search from.
* @return the index of the first occurrence of the character in the
* character sequence represented by this object that is greater
- * than or equal to <code>fromIndex</code>, or <code>-1</code>
+ * than or equal to {@code fromIndex}, or {@code -1}
* if the character does not occur.
*/
public int indexOf(int ch, int fromIndex) {
@@ -1486,26 +1510,26 @@
/**
* Returns the index within this string of the last occurrence of
- * the specified character. For values of <code>ch</code> in the
+ * the specified character. For values of {@code ch} in the
* range from 0 to 0xFFFF (inclusive), the index (in Unicode code
* units) returned is the largest value <i>k</i> such that:
* <blockquote><pre>
* this.charAt(<i>k</i>) == ch
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* largest value <i>k</i> such that:
* <blockquote><pre>
* this.codePointAt(<i>k</i>) == ch
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string, then <code>-1</code> is returned. The
- * <code>String</code> is searched backwards starting at the last
+ * string, then {@code -1} is returned. The
+ * {@code String} is searched backwards starting at the last
* character.
*
* @param ch a character (Unicode code point).
* @return the index of the last occurrence of the character in the
* character sequence represented by this object, or
- * <code>-1</code> if the character does not occur.
+ * {@code -1} if the character does not occur.
*/
public int lastIndexOf(int ch) {
return lastIndexOf(ch, count - 1);
@@ -1514,27 +1538,27 @@
/**
* Returns the index within this string of the last occurrence of
* the specified character, searching backward starting at the
- * specified index. For values of <code>ch</code> in the range
+ * specified index. For values of {@code ch} in the range
* from 0 to 0xFFFF (inclusive), the index returned is the largest
* value <i>k</i> such that:
* <blockquote><pre>
- * (this.charAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex)
+ * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> <= fromIndex)
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* largest value <i>k</i> such that:
* <blockquote><pre>
- * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex)
+ * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> <= fromIndex)
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string at or before position <code>fromIndex</code>, then
- * <code>-1</code> is returned.
+ * string at or before position {@code fromIndex}, then
+ * {@code -1} is returned.
*
- * <p>All indices are specified in <code>char</code> values
+ * <p>All indices are specified in {@code char} values
* (Unicode code units).
*
* @param ch a character (Unicode code point).
* @param fromIndex the index to start the search from. There is no
- * restriction on the value of <code>fromIndex</code>. If it is
+ * restriction on the value of {@code fromIndex}. If it is
* greater than or equal to the length of this string, it has
* the same effect as if it were equal to one less than the
* length of this string: this entire string may be searched.
@@ -1542,7 +1566,7 @@
* -1 is returned.
* @return the index of the last occurrence of the character in the
* character sequence represented by this object that is less
- * than or equal to <code>fromIndex</code>, or <code>-1</code>
+ * than or equal to {@code fromIndex}, or {@code -1}
* if the character does not occur before that point.
*/
public int lastIndexOf(int ch, int fromIndex) {
@@ -1602,7 +1626,7 @@
*
* <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
- * <i>k</i> >= fromIndex && this.startsWith(str, <i>k</i>)
+ * <i>k</i> >= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
@@ -1617,7 +1641,7 @@
}
/**
- * Code shared by String and StringBuffer to do searches. The
+ * Code shared by String and AbstractStringBuilder to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
*
@@ -1739,7 +1763,7 @@
*
* <p>The returned index is the largest value <i>k</i> for which:
* <blockquote><pre>
- * <i>k</i> <= fromIndex && this.startsWith(str, <i>k</i>)
+ * <i>k</i> {@code <=} fromIndex {@code &&} this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
@@ -1754,16 +1778,12 @@
}
/**
- * Code shared by String and StringBuffer to do searches. The
+ * Code shared by String and AbstractStringBuilder to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
*
* @param source the characters being searched.
- * @param sourceOffset offset of the source string.
- * @param sourceCount count of the source string.
* @param target the characters being searched for.
- * @param targetOffset offset of the target string.
- * @param targetCount count of the target string.
* @param fromIndex the index to begin searching from.
*/
static int lastIndexOf(String source,
@@ -1849,7 +1869,7 @@
int min = sourceOffset + targetCount - 1;
int i = min + fromIndex;
- startSearchForLastChar:
+ startSearchForLastChar:
while (true) {
while (i >= min && source[i] != strLastChar) {
i--;
@@ -1872,7 +1892,7 @@
}
/**
- * Returns a new string that is a substring of this string. The
+ * Returns a string that is a substring of this string. The
* substring begins with the character at the specified index and
* extends to the end of this string. <p>
* Examples:
@@ -1885,8 +1905,8 @@
* @param beginIndex the beginning index, inclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if
- * <code>beginIndex</code> is negative or larger than the
- * length of this <code>String</code> object.
+ * {@code beginIndex} is negative or larger than the
+ * length of this {@code String} object.
*/
public String substring(int beginIndex) {
if (beginIndex < 0) {
@@ -1900,10 +1920,10 @@
}
/**
- * Returns a new string that is a substring of this string. The
- * substring begins at the specified <code>beginIndex</code> and
- * extends to the character at index <code>endIndex - 1</code>.
- * Thus the length of the substring is <code>endIndex-beginIndex</code>.
+ * Returns a string that is a substring of this string. The
+ * substring begins at the specified {@code beginIndex} and
+ * extends to the character at index {@code endIndex - 1}.
+ * Thus the length of the substring is {@code endIndex-beginIndex}.
* <p>
* Examples:
* <blockquote><pre>
@@ -1915,20 +1935,22 @@
* @param endIndex the ending index, exclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if the
- * <code>beginIndex</code> is negative, or
- * <code>endIndex</code> is larger than the length of
- * this <code>String</code> object, or
- * <code>beginIndex</code> is larger than
- * <code>endIndex</code>.
+ * {@code beginIndex} is negative, or
+ * {@code endIndex} is larger than the length of
+ * this {@code String} object, or
+ * {@code beginIndex} is larger than
+ * {@code endIndex}.
*/
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(this, beginIndex);
}
-
+ if (endIndex > count) {
+ throw new StringIndexOutOfBoundsException(this, endIndex);
+ }
int subLen = endIndex - beginIndex;
- if (endIndex > count || subLen < 0) {
- throw new StringIndexOutOfBoundsException(this, beginIndex, subLen);
+ if (subLen < 0) {
+ throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == count)) ? this
@@ -1938,7 +1960,7 @@
private native String fastSubstring(int start, int length);
/**
- * Returns a new character sequence that is a subsequence of this sequence.
+ * Returns a character sequence that is a subsequence of this sequence.
*
* <p> An invocation of this method of the form
*
@@ -1950,17 +1972,18 @@
* <blockquote><pre>
* str.substring(begin, end)</pre></blockquote>
*
- * This method is defined so that the <tt>String</tt> class can implement
- * the {@link CharSequence} interface. </p>
+ * @apiNote
+ * This method is defined so that the {@code String} class can implement
+ * the {@link CharSequence} interface.
*
- * @param beginIndex the begin index, inclusive.
- * @param endIndex the end index, exclusive.
- * @return the specified subsequence.
+ * @param beginIndex the begin index, inclusive.
+ * @param endIndex the end index, exclusive.
+ * @return the specified subsequence.
*
* @throws IndexOutOfBoundsException
- * if <tt>beginIndex</tt> or <tt>endIndex</tt> are negative,
- * if <tt>endIndex</tt> is greater than <tt>length()</tt>,
- * or if <tt>beginIndex</tt> is greater than <tt>startIndex</tt>
+ * if {@code beginIndex} or {@code endIndex} is negative,
+ * if {@code endIndex} is greater than {@code length()},
+ * or if {@code beginIndex} is greater than {@code endIndex}
*
* @since 1.4
* @spec JSR-51
@@ -1972,11 +1995,11 @@
/**
* Concatenates the specified string to the end of this string.
* <p>
- * If the length of the argument string is <code>0</code>, then this
- * <code>String</code> object is returned. Otherwise, a new
- * <code>String</code> object is created, representing a character
+ * If the length of the argument string is {@code 0}, then this
+ * {@code String} object is returned. Otherwise, a
+ * {@code String} object is returned that represents a character
* sequence that is the concatenation of the character sequence
- * represented by this <code>String</code> object and the character
+ * represented by this {@code String} object and the character
* sequence represented by the argument string.<p>
* Examples:
* <blockquote><pre>
@@ -1984,25 +2007,25 @@
* "to".concat("get").concat("her") returns "together"
* </pre></blockquote>
*
- * @param str the <code>String</code> that is concatenated to the end
- * of this <code>String</code>.
+ * @param str the {@code String} that is concatenated to the end
+ * of this {@code String}.
* @return a string that represents the concatenation of this object's
* characters followed by the string argument's characters.
*/
public native String concat(String str);
/**
- * Returns a new string resulting from replacing all occurrences of
- * <code>oldChar</code> in this string with <code>newChar</code>.
+ * Returns a string resulting from replacing all occurrences of
+ * {@code oldChar} in this string with {@code newChar}.
* <p>
- * If the character <code>oldChar</code> does not occur in the
- * character sequence represented by this <code>String</code> object,
- * then a reference to this <code>String</code> object is returned.
- * Otherwise, a new <code>String</code> object is created that
+ * If the character {@code oldChar} does not occur in the
+ * character sequence represented by this {@code String} object,
+ * then a reference to this {@code String} object is returned.
+ * Otherwise, a {@code String} object is returned that
* represents a character sequence identical to the character sequence
- * represented by this <code>String</code> object, except that every
- * occurrence of <code>oldChar</code> is replaced by an occurrence
- * of <code>newChar</code>.
+ * represented by this {@code String} object, except that every
+ * occurrence of {@code oldChar} is replaced by an occurrence
+ * of {@code newChar}.
* <p>
* Examples:
* <blockquote><pre>
@@ -2018,7 +2041,7 @@
* @param oldChar the old character.
* @param newChar the new character.
* @return a string derived from this string by replacing every
- * occurrence of <code>oldChar</code> with <code>newChar</code>.
+ * occurrence of {@code oldChar} with {@code newChar}.
*/
public String replace(char oldChar, char newChar) {
String replaced = this;
@@ -2040,17 +2063,18 @@
* href="../util/regex/Pattern.html#sum">regular expression</a>.
*
* <p> An invocation of this method of the form
- * <i>str</i><tt>.matches(</tt><i>regex</i><tt>)</tt> yields exactly the
+ * <i>str</i>{@code .matches(}<i>regex</i>{@code )} yields exactly the
* same result as the expression
*
- * <blockquote><tt> {@link java.util.regex.Pattern}.{@link
- * java.util.regex.Pattern#matches(String,CharSequence)
- * matches}(</tt><i>regex</i><tt>,</tt> <i>str</i><tt>)</tt></blockquote>
+ * <blockquote>
+ * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#matches(String,CharSequence)
+ * matches(<i>regex</i>, <i>str</i>)}
+ * </blockquote>
*
* @param regex
* the regular expression to which this string is to be matched
*
- * @return <tt>true</tt> if, and only if, this string matches the
+ * @return {@code true} if, and only if, this string matches the
* given regular expression
*
* @throws PatternSyntaxException
@@ -2070,8 +2094,7 @@
* sequence of char values.
*
* @param s the sequence to search for
- * @return true if this string contains <code>s</code>, false otherwise
- * @throws NullPointerException if <code>s</code> is <code>null</code>
+ * @return true if this string contains {@code s}, false otherwise
* @since 1.5
*/
public boolean contains(CharSequence s) {
@@ -2084,18 +2107,20 @@
* given replacement.
*
* <p> An invocation of this method of the form
- * <i>str</i><tt>.replaceFirst(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+ * <i>str</i>{@code .replaceFirst(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
* yields exactly the same result as the expression
*
- * <blockquote><tt>
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
- * compile}(</tt><i>regex</i><tt>).{@link
- * java.util.regex.Pattern#matcher(java.lang.CharSequence)
- * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceFirst
- * replaceFirst}(</tt><i>repl</i><tt>)</tt></blockquote>
+ * <blockquote>
+ * <code>
+ * {@link java.util.regex.Pattern}.{@link
+ * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+ * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+ * java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
+ * </code>
+ * </blockquote>
*
*<p>
- * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+ * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
* replacement string may cause the results to be different than if it were
* being treated as a literal replacement string; see
* {@link java.util.regex.Matcher#replaceFirst}.
@@ -2107,7 +2132,7 @@
* @param replacement
* the string to be substituted for the first match
*
- * @return The resulting <tt>String</tt>
+ * @return The resulting {@code String}
*
* @throws PatternSyntaxException
* if the regular expression's syntax is invalid
@@ -2127,18 +2152,20 @@
* given replacement.
*
* <p> An invocation of this method of the form
- * <i>str</i><tt>.replaceAll(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
+ * <i>str</i>{@code .replaceAll(}<i>regex</i>{@code ,} <i>repl</i>{@code )}
* yields exactly the same result as the expression
*
- * <blockquote><tt>
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
- * compile}(</tt><i>regex</i><tt>).{@link
- * java.util.regex.Pattern#matcher(java.lang.CharSequence)
- * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceAll
- * replaceAll}(</tt><i>repl</i><tt>)</tt></blockquote>
+ * <blockquote>
+ * <code>
+ * {@link java.util.regex.Pattern}.{@link
+ * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+ * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(<i>str</i>).{@link
+ * java.util.regex.Matcher#replaceAll replaceAll}(<i>repl</i>)
+ * </code>
+ * </blockquote>
*
*<p>
- * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
+ * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
* replacement string may cause the results to be different than if it were
* being treated as a literal replacement string; see
* {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}.
@@ -2150,7 +2177,7 @@
* @param replacement
* the string to be substituted for each match
*
- * @return The resulting <tt>String</tt>
+ * @return The resulting {@code String}
*
* @throws PatternSyntaxException
* if the regular expression's syntax is invalid
@@ -2246,7 +2273,12 @@
* expression does not match any part of the input then the resulting array
* has just one element, namely this string.
*
- * <p> The <tt>limit</tt> parameter controls the number of times the
+ * <p> When there is a positive-width match at the beginning of this
+ * string then an empty leading substring is included at the beginning
+ * of the resulting array. A zero-width match at the beginning however
+ * never produces such empty leading substring.
+ *
+ * <p> The {@code limit} parameter controls the number of times the
* pattern is applied and therefore affects the length of the resulting
* array. If the limit <i>n</i> is greater than zero then the pattern
* will be applied at most <i>n</i> - 1 times, the array's
@@ -2257,7 +2289,7 @@
* the pattern will be applied as many times as possible, the array can
* have any length, and trailing empty strings will be discarded.
*
- * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the
+ * <p> The string {@code "boo:and:foo"}, for example, yields the
* following results with these parameters:
*
* <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
@@ -2268,33 +2300,34 @@
* </tr>
* <tr><td align=center>:</td>
* <td align=center>2</td>
- * <td><tt>{ "boo", "and:foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and:foo" }}</td></tr>
* <tr><td align=center>:</td>
* <td align=center>5</td>
- * <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and", "foo" }}</td></tr>
* <tr><td align=center>:</td>
* <td align=center>-2</td>
- * <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and", "foo" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>5</td>
- * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>-2</td>
- * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>0</td>
- * <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f" }}</td></tr>
* </table></blockquote>
*
* <p> An invocation of this method of the form
- * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt> <i>n</i><tt>)</tt>
+ * <i>str.</i>{@code split(}<i>regex</i>{@code ,} <i>n</i>{@code )}
* yields the same result as the expression
*
* <blockquote>
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
- * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link
- * java.util.regex.Pattern#split(java.lang.CharSequence,int)
- * split}<tt>(</tt><i>str</i><tt>,</tt> <i>n</i><tt>)</tt>
+ * <code>
+ * {@link java.util.regex.Pattern}.{@link
+ * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+ * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(<i>str</i>, <i>n</i>)
+ * </code>
* </blockquote>
*
*
@@ -2334,7 +2367,7 @@
* argument of zero. Trailing empty strings are therefore not included in
* the resulting array.
*
- * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the following
+ * <p> The string {@code "boo:and:foo"}, for example, yields the following
* results with these expressions:
*
* <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result">
@@ -2343,9 +2376,9 @@
* <th>Result</th>
* </tr>
* <tr><td align=center>:</td>
- * <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and", "foo" }}</td></tr>
* <tr><td align=center>o</td>
- * <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f" }}</td></tr>
* </table></blockquote>
*
*
@@ -2368,11 +2401,95 @@
}
/**
- * Converts all of the characters in this <code>String</code> to lower
- * case using the rules of the given <code>Locale</code>. Case mapping is based
+ * Returns a new String composed of copies of the
+ * {@code CharSequence elements} joined together with a copy of
+ * the specified {@code delimiter}.
+ *
+ * <blockquote>For example,
+ * <pre>{@code
+ * String message = String.join("-", "Java", "is", "cool");
+ * // message returned is: "Java-is-cool"
+ * }</pre></blockquote>
+ *
+ * Note that if an element is null, then {@code "null"} is added.
+ *
+ * @param delimiter the delimiter that separates each element
+ * @param elements the elements to join together.
+ *
+ * @return a new {@code String} that is composed of the {@code elements}
+ * separated by the {@code delimiter}
+ *
+ * @throws NullPointerException If {@code delimiter} or {@code elements}
+ * is {@code null}
+ *
+ * @see java.util.StringJoiner
+ * @since 1.8
+ */
+ public static String join(CharSequence delimiter, CharSequence... elements) {
+ Objects.requireNonNull(delimiter);
+ Objects.requireNonNull(elements);
+ // Number of elements not likely worth Arrays.stream overhead.
+ StringJoiner joiner = new StringJoiner(delimiter);
+ for (CharSequence cs: elements) {
+ joiner.add(cs);
+ }
+ return joiner.toString();
+ }
+
+ /**
+ * Returns a new {@code String} composed of copies of the
+ * {@code CharSequence elements} joined together with a copy of the
+ * specified {@code delimiter}.
+ *
+ * <blockquote>For example,
+ * <pre>{@code
+ * List<String> strings = new LinkedList<>();
+ * strings.add("Java");strings.add("is");
+ * strings.add("cool");
+ * String message = String.join(" ", strings);
+ * //message returned is: "Java is cool"
+ *
+ * Set<String> strings = new LinkedHashSet<>();
+ * strings.add("Java"); strings.add("is");
+ * strings.add("very"); strings.add("cool");
+ * String message = String.join("-", strings);
+ * //message returned is: "Java-is-very-cool"
+ * }</pre></blockquote>
+ *
+ * Note that if an individual element is {@code null}, then {@code "null"} is added.
+ *
+ * @param delimiter a sequence of characters that is used to separate each
+ * of the {@code elements} in the resulting {@code String}
+ * @param elements an {@code Iterable} that will have its {@code elements}
+ * joined together.
+ *
+ * @return a new {@code String} that is composed from the {@code elements}
+ * argument
+ *
+ * @throws NullPointerException If {@code delimiter} or {@code elements}
+ * is {@code null}
+ *
+ * @see #join(CharSequence,CharSequence...)
+ * @see java.util.StringJoiner
+ * @since 1.8
+ */
+ public static String join(CharSequence delimiter,
+ Iterable<? extends CharSequence> elements) {
+ Objects.requireNonNull(delimiter);
+ Objects.requireNonNull(elements);
+ StringJoiner joiner = new StringJoiner(delimiter);
+ for (CharSequence cs: elements) {
+ joiner.add(cs);
+ }
+ return joiner.toString();
+ }
+
+ /**
+ * Converts all of the characters in this {@code String} to lower
+ * case using the rules of the given {@code Locale}. Case mapping is based
* on the Unicode Standard version specified by the {@link java.lang.Character Character}
* class. Since case mappings are not always 1:1 char mappings, the resulting
- * <code>String</code> may be a different length than the original <code>String</code>.
+ * {@code String} may be a different length than the original {@code String}.
* <p>
* Examples of lowercase mappings are in the following table:
* <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description">
@@ -2413,7 +2530,7 @@
* </table>
*
* @param locale use the case transformation rules for this locale
- * @return the <code>String</code>, converted to lowercase.
+ * @return the {@code String}, converted to lowercase.
* @see java.lang.String#toLowerCase()
* @see java.lang.String#toUpperCase()
* @see java.lang.String#toUpperCase(Locale)
@@ -2424,22 +2541,22 @@
}
/**
- * Converts all of the characters in this <code>String</code> to lower
+ * Converts all of the characters in this {@code String} to lower
* case using the rules of the default locale. This is equivalent to calling
- * <code>toLowerCase(Locale.getDefault())</code>.
+ * {@code toLowerCase(Locale.getDefault())}.
* <p>
* <b>Note:</b> This method is locale sensitive, and may produce unexpected
* results if used for strings that are intended to be interpreted locale
* independently.
* Examples are programming language identifiers, protocol keys, and HTML
* tags.
- * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale
- * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the
+ * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale
+ * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the
* LATIN SMALL LETTER DOTLESS I character.
* To obtain correct results for locale insensitive strings, use
- * <code>toLowerCase(Locale.ENGLISH)</code>.
+ * {@code toLowerCase(Locale.ROOT)}.
* <p>
- * @return the <code>String</code>, converted to lowercase.
+ * @return the {@code String}, converted to lowercase.
* @see java.lang.String#toLowerCase(Locale)
*/
public String toLowerCase() {
@@ -2447,14 +2564,14 @@
}
/**
- * Converts all of the characters in this <code>String</code> to upper
- * case using the rules of the given <code>Locale</code>. Case mapping is based
+ * Converts all of the characters in this {@code String} to upper
+ * case using the rules of the given {@code Locale}. Case mapping is based
* on the Unicode Standard version specified by the {@link java.lang.Character Character}
* class. Since case mappings are not always 1:1 char mappings, the resulting
- * <code>String</code> may be a different length than the original <code>String</code>.
+ * {@code String} may be a different length than the original {@code String}.
* <p>
* Examples of locale-sensitive and 1:M case mappings are in the following table.
- * <p>
+ *
* <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
* <tr>
* <th>Language Code of Locale</th>
@@ -2488,7 +2605,7 @@
* </tr>
* </table>
* @param locale use the case transformation rules for this locale
- * @return the <code>String</code>, converted to uppercase.
+ * @return the {@code String}, converted to uppercase.
* @see java.lang.String#toUpperCase()
* @see java.lang.String#toLowerCase()
* @see java.lang.String#toLowerCase(Locale)
@@ -2499,22 +2616,22 @@
}
/**
- * Converts all of the characters in this <code>String</code> to upper
+ * Converts all of the characters in this {@code String} to upper
* case using the rules of the default locale. This method is equivalent to
- * <code>toUpperCase(Locale.getDefault())</code>.
+ * {@code toUpperCase(Locale.getDefault())}.
* <p>
* <b>Note:</b> This method is locale sensitive, and may produce unexpected
* results if used for strings that are intended to be interpreted locale
* independently.
* Examples are programming language identifiers, protocol keys, and HTML
* tags.
- * For instance, <code>"title".toUpperCase()</code> in a Turkish locale
- * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the
+ * For instance, {@code "title".toUpperCase()} in a Turkish locale
+ * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the
* LATIN CAPITAL LETTER I WITH DOT ABOVE character.
* To obtain correct results for locale insensitive strings, use
- * <code>toUpperCase(Locale.ENGLISH)</code>.
+ * {@code toUpperCase(Locale.ROOT)}.
* <p>
- * @return the <code>String</code>, converted to uppercase.
+ * @return the {@code String}, converted to uppercase.
* @see java.lang.String#toUpperCase(Locale)
*/
public String toUpperCase() {
@@ -2522,33 +2639,33 @@
}
/**
- * Returns a copy of the string, with leading and trailing whitespace
- * omitted.
+ * Returns a string whose value is this string, with any leading and trailing
+ * whitespace removed.
* <p>
- * If this <code>String</code> object represents an empty character
+ * If this {@code String} object represents an empty character
* sequence, or the first and last characters of character sequence
- * represented by this <code>String</code> object both have codes
- * greater than <code>'\u0020'</code> (the space character), then a
- * reference to this <code>String</code> object is returned.
+ * represented by this {@code String} object both have codes
+ * greater than {@code '\u005Cu0020'} (the space character), then a
+ * reference to this {@code String} object is returned.
* <p>
* Otherwise, if there is no character with a code greater than
- * <code>'\u0020'</code> in the string, then a new
- * <code>String</code> object representing an empty string is created
- * and returned.
+ * {@code '\u005Cu0020'} in the string, then a
+ * {@code String} object representing an empty string is
+ * returned.
* <p>
* Otherwise, let <i>k</i> be the index of the first character in the
- * string whose code is greater than <code>'\u0020'</code>, and let
+ * string whose code is greater than {@code '\u005Cu0020'}, and let
* <i>m</i> be the index of the last character in the string whose code
- * is greater than <code>'\u0020'</code>. A new <code>String</code>
- * object is created, representing the substring of this string that
+ * is greater than {@code '\u005Cu0020'}. A {@code String}
+ * object is returned, representing the substring of this string that
* begins with the character at index <i>k</i> and ends with the
* character at index <i>m</i>-that is, the result of
- * <code>this.substring(<i>k</i>, <i>m</i>+1)</code>.
+ * {@code this.substring(k, m + 1)}.
* <p>
* This method may be used to trim whitespace (as defined above) from
* the beginning and end of a string.
*
- * @return A copy of this string with leading and trailing white
+ * @return A string whose value is this string, with any leading and trailing white
* space removed, or this string if it has no leading or
* trailing white space.
*/
@@ -2602,10 +2719,10 @@
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java™ Virtual Machine Specification</cite>.
* The behaviour on a
- * <tt>null</tt> argument depends on the <a
+ * {@code null} argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -2632,7 +2749,7 @@
*
* @param l
* The {@linkplain java.util.Locale locale} to apply during
- * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
+ * formatting. If {@code l} is {@code null} then no localization
* is applied.
*
* @param format
@@ -2646,10 +2763,10 @@
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java™ Virtual Machine Specification</cite>.
* The behaviour on a
- * <tt>null</tt> argument depends on the <a
- * href="../util/Formatter.html#syntax">conversion</a>.
+ * {@code null} argument depends on the
+ * <a href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -2671,12 +2788,12 @@
}
/**
- * Returns the string representation of the <code>Object</code> argument.
+ * Returns the string representation of the {@code Object} argument.
*
- * @param obj an <code>Object</code>.
- * @return if the argument is <code>null</code>, then a string equal to
- * <code>"null"</code>; otherwise, the value of
- * <code>obj.toString()</code> is returned.
+ * @param obj an {@code Object}.
+ * @return if the argument is {@code null}, then a string equal to
+ * {@code "null"}; otherwise, the value of
+ * {@code obj.toString()} is returned.
* @see java.lang.Object#toString()
*/
public static String valueOf(Object obj) {
@@ -2684,14 +2801,14 @@
}
/**
- * Returns the string representation of the <code>char</code> array
+ * Returns the string representation of the {@code char} array
* argument. The contents of the character array are copied; subsequent
- * modification of the character array does not affect the newly
- * created string.
+ * modification of the character array does not affect the returned
+ * string.
*
- * @param data a <code>char</code> array.
- * @return a newly allocated string representing the same sequence of
- * characters contained in the character array argument.
+ * @param data the character array.
+ * @return a {@code String} that contains the characters of the
+ * character array.
*/
public static String valueOf(char data[]) {
return StringFactory.newStringFromChars(data);
@@ -2699,38 +2816,40 @@
/**
* Returns the string representation of a specific subarray of the
- * <code>char</code> array argument.
+ * {@code char} array argument.
* <p>
- * The <code>offset</code> argument is the index of the first
- * character of the subarray. The <code>count</code> argument
+ * The {@code offset} argument is the index of the first
+ * character of the subarray. The {@code count} argument
* specifies the length of the subarray. The contents of the subarray
* are copied; subsequent modification of the character array does not
- * affect the newly created string.
+ * affect the returned string.
*
* @param data the character array.
- * @param offset the initial offset into the value of the
- * <code>String</code>.
- * @param count the length of the value of the <code>String</code>.
- * @return a string representing the sequence of characters contained
- * in the subarray of the character array argument.
- * @exception IndexOutOfBoundsException if <code>offset</code> is
- * negative, or <code>count</code> is negative, or
- * <code>offset+count</code> is larger than
- * <code>data.length</code>.
+ * @param offset initial offset of the subarray.
+ * @param count length of the subarray.
+ * @return a {@code String} that contains the characters of the
+ * specified subarray of the character array.
+ * @exception IndexOutOfBoundsException if {@code offset} is
+ * negative, or {@code count} is negative, or
+ * {@code offset+count} is larger than
+ * {@code data.length}.
*/
public static String valueOf(char data[], int offset, int count) {
return StringFactory.newStringFromChars(data, offset, count);
}
/**
- * Returns a String that represents the character sequence in the
- * array specified.
+ * Equivalent to {@link #valueOf(char[], int, int)}.
*
* @param data the character array.
* @param offset initial offset of the subarray.
* @param count length of the subarray.
- * @return a <code>String</code> that contains the characters of the
+ * @return a {@code String} that contains the characters of the
* specified subarray of the character array.
+ * @exception IndexOutOfBoundsException if {@code offset} is
+ * negative, or {@code count} is negative, or
+ * {@code offset+count} is larger than
+ * {@code data.length}.
*/
public static String copyValueOf(char data[], int offset, int count) {
// All public String constructors now copy the data.
@@ -2738,11 +2857,10 @@
}
/**
- * Returns a String that represents the character sequence in the
- * array specified.
+ * Equivalent to {@link #valueOf(char[])}.
*
* @param data the character array.
- * @return a <code>String</code> that contains the characters of the
+ * @return a {@code String} that contains the characters of the
* character array.
*/
public static String copyValueOf(char data[]) {
@@ -2750,37 +2868,37 @@
}
/**
- * Returns the string representation of the <code>boolean</code> argument.
+ * Returns the string representation of the {@code boolean} argument.
*
- * @param b a <code>boolean</code>.
- * @return if the argument is <code>true</code>, a string equal to
- * <code>"true"</code> is returned; otherwise, a string equal to
- * <code>"false"</code> is returned.
+ * @param b a {@code boolean}.
+ * @return if the argument is {@code true}, a string equal to
+ * {@code "true"} is returned; otherwise, a string equal to
+ * {@code "false"} is returned.
*/
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
/**
- * Returns the string representation of the <code>char</code>
+ * Returns the string representation of the {@code char}
* argument.
*
- * @param c a <code>char</code>.
- * @return a string of length <code>1</code> containing
- * as its single character the argument <code>c</code>.
+ * @param c a {@code char}.
+ * @return a string of length {@code 1} containing
+ * as its single character the argument {@code c}.
*/
public static String valueOf(char c) {
return StringFactory.newStringFromChars(0, 1, new char[] { c });
}
/**
- * Returns the string representation of the <code>int</code> argument.
+ * Returns the string representation of the {@code int} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Integer.toString</code> method of one argument.
+ * {@code Integer.toString} method of one argument.
*
- * @param i an <code>int</code>.
- * @return a string representation of the <code>int</code> argument.
+ * @param i an {@code int}.
+ * @return a string representation of the {@code int} argument.
* @see java.lang.Integer#toString(int, int)
*/
public static String valueOf(int i) {
@@ -2788,13 +2906,13 @@
}
/**
- * Returns the string representation of the <code>long</code> argument.
+ * Returns the string representation of the {@code long} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Long.toString</code> method of one argument.
+ * {@code Long.toString} method of one argument.
*
- * @param l a <code>long</code>.
- * @return a string representation of the <code>long</code> argument.
+ * @param l a {@code long}.
+ * @return a string representation of the {@code long} argument.
* @see java.lang.Long#toString(long)
*/
public static String valueOf(long l) {
@@ -2802,13 +2920,13 @@
}
/**
- * Returns the string representation of the <code>float</code> argument.
+ * Returns the string representation of the {@code float} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Float.toString</code> method of one argument.
+ * {@code Float.toString} method of one argument.
*
- * @param f a <code>float</code>.
- * @return a string representation of the <code>float</code> argument.
+ * @param f a {@code float}.
+ * @return a string representation of the {@code float} argument.
* @see java.lang.Float#toString(float)
*/
public static String valueOf(float f) {
@@ -2816,13 +2934,13 @@
}
/**
- * Returns the string representation of the <code>double</code> argument.
+ * Returns the string representation of the {@code double} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Double.toString</code> method of one argument.
+ * {@code Double.toString} method of one argument.
*
- * @param d a <code>double</code>.
- * @return a string representation of the <code>double</code> argument.
+ * @param d a {@code double}.
+ * @return a string representation of the {@code double} argument.
* @see java.lang.Double#toString(double)
*/
public static String valueOf(double d) {
@@ -2833,17 +2951,17 @@
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
- * class <code>String</code>.
+ * class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
- * string equal to this <code>String</code> object as determined by
+ * string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
- * returned. Otherwise, this <code>String</code> object is added to the
- * pool and a reference to this <code>String</code> object is returned.
+ * returned. Otherwise, this {@code String} object is added to the
+ * pool and a reference to this {@code String} object is returned.
* <p>
- * It follows that for any two strings <code>s</code> and <code>t</code>,
- * <code>s.intern() == t.intern()</code> is <code>true</code>
- * if and only if <code>s.equals(t)</code> is <code>true</code>.
+ * It follows that for any two strings {@code s} and {@code t},
+ * {@code s.intern() == t.intern()} is {@code true}
+ * if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
diff --git a/ojluni/src/main/java/java/lang/StringBuffer.java b/ojluni/src/main/java/java/lang/StringBuffer.java
old mode 100755
new mode 100644
index d832881..95a583d
--- a/ojluni/src/main/java/java/lang/StringBuffer.java
+++ b/ojluni/src/main/java/java/lang/StringBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package java.lang;
+import java.util.Arrays;
/**
* A thread-safe, mutable sequence of characters.
@@ -39,39 +40,52 @@
* that is consistent with the order of the method calls made by each of
* the individual threads involved.
* <p>
- * The principal operations on a <code>StringBuffer</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * The principal operations on a {@code StringBuffer} are the
+ * {@code append} and {@code insert} methods, which are
* overloaded so as to accept data of any type. Each effectively
* converts a given datum to a string and then appends or inserts the
* characters of that string to the string buffer. The
- * <code>append</code> method always adds these characters at the end
- * of the buffer; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the buffer; the {@code insert} method adds the characters at
* a specified point.
* <p>
- * For example, if <code>z</code> refers to a string buffer object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * buffer to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string buffer to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string buffer object
+ * whose current contents are {@code "start"}, then
+ * the method call {@code z.append("le")} would cause the string
+ * buffer to contain {@code "startle"}, whereas
+ * {@code z.insert(4, "le")} would alter the string buffer to
+ * contain {@code "starlet"}.
* <p>
- * In general, if sb refers to an instance of a <code>StringBuffer</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(), x)</code>.
+ * In general, if sb refers to an instance of a {@code StringBuffer},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(), x)}.
* <p>
* Whenever an operation occurs involving a source sequence (such as
- * appending or inserting from a source sequence) this class synchronizes
+ * appending or inserting from a source sequence), this class synchronizes
* only on the string buffer performing the operation, not on the source.
+ * Note that while {@code StringBuffer} is designed to be safe to use
+ * concurrently from multiple threads, if the constructor or the
+ * {@code append} or {@code insert} operation is passed a source sequence
+ * that is shared across threads, the calling code must ensure
+ * that the operation has a consistent and unchanging view of the source
+ * sequence for the duration of the operation.
+ * This could be satisfied by the caller holding a lock during the
+ * operation's call, by using an immutable source sequence, or by not
+ * sharing the source sequence across threads.
* <p>
* Every string buffer has a capacity. As long as the length of the
* character sequence contained in the string buffer does not exceed
* the capacity, it is not necessary to allocate a new internal
* buffer array. If the internal buffer overflows, it is
* automatically made larger.
- *
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ * <p>
* As of release JDK 5, this class has been supplemented with an equivalent
* class designed for use by a single thread, {@link StringBuilder}. The
- * <tt>StringBuilder</tt> class should generally be used in preference to
+ * {@code StringBuilder} class should generally be used in preference to
* this one, as it supports all of the same operations but it is faster, as
* it performs no synchronization.
*
@@ -82,9 +96,15 @@
*/
public final class StringBuffer
extends AbstractStringBuilder
- implements java.io.Serializable, Appendable, CharSequence
+ implements java.io.Serializable, CharSequence
{
+ /**
+ * A cache of the last value returned by toString. Cleared
+ * whenever the StringBuffer is modified.
+ */
+ private transient char[] toStringCache;
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
static final long serialVersionUID = 3388685877147921107L;
@@ -101,8 +121,8 @@
* the specified initial capacity.
*
* @param capacity the initial capacity.
- * @exception NegativeArraySizeException if the <code>capacity</code>
- * argument is less than <code>0</code>.
+ * @exception NegativeArraySizeException if the {@code capacity}
+ * argument is less than {@code 0}.
*/
public StringBuffer(int capacity) {
super(capacity);
@@ -111,10 +131,9 @@
/**
* Constructs a string buffer initialized to the contents of the
* specified string. The initial capacity of the string buffer is
- * <code>16</code> plus the length of the string argument.
+ * {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
- * @exception NullPointerException if <code>str</code> is <code>null</code>
*/
public StringBuffer(String str) {
super(str.length() + 16);
@@ -123,16 +142,15 @@
/**
* Constructs a string buffer that contains the same characters
- * as the specified <code>CharSequence</code>. The initial capacity of
- * the string buffer is <code>16</code> plus the length of the
- * <code>CharSequence</code> argument.
+ * as the specified {@code CharSequence}. The initial capacity of
+ * the string buffer is {@code 16} plus the length of the
+ * {@code CharSequence} argument.
* <p>
- * If the length of the specified <code>CharSequence</code> is
+ * If the length of the specified {@code CharSequence} is
* less than or equal to zero, then an empty buffer of capacity
- * <code>16</code> is returned.
+ * {@code 16} is returned.
*
* @param seq the sequence to copy.
- * @exception NullPointerException if <code>seq</code> is <code>null</code>
* @since 1.5
*/
public StringBuffer(CharSequence seq) {
@@ -140,15 +158,18 @@
append(seq);
}
+ @Override
public synchronized int length() {
return count;
}
+ @Override
public synchronized int capacity() {
return value.length;
}
+ @Override
public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
@@ -158,6 +179,7 @@
/**
* @since 1.5
*/
+ @Override
public synchronized void trimToSize() {
super.trimToSize();
}
@@ -166,7 +188,9 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
+ @Override
public synchronized void setLength(int newLength) {
+ toStringCache = null;
super.setLength(newLength);
}
@@ -174,6 +198,7 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
+ @Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
@@ -183,6 +208,7 @@
/**
* @since 1.5
*/
+ @Override
public synchronized int codePointAt(int index) {
return super.codePointAt(index);
}
@@ -190,6 +216,7 @@
/**
* @since 1.5
*/
+ @Override
public synchronized int codePointBefore(int index) {
return super.codePointBefore(index);
}
@@ -197,6 +224,7 @@
/**
* @since 1.5
*/
+ @Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
return super.codePointCount(beginIndex, endIndex);
}
@@ -204,14 +232,15 @@
/**
* @since 1.5
*/
+ @Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
return super.offsetByCodePoints(index, codePointOffset);
}
/**
- * @throws NullPointerException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)
{
@@ -222,95 +251,111 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
+ @Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
+ toStringCache = null;
value[index] = ch;
}
+ @Override
public synchronized StringBuffer append(Object obj) {
+ toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
+ @Override
public synchronized StringBuffer append(String str) {
+ toStringCache = null;
super.append(str);
return this;
}
/**
- * Appends the specified <tt>StringBuffer</tt> to this sequence.
+ * Appends the specified {@code StringBuffer} to this sequence.
* <p>
- * The characters of the <tt>StringBuffer</tt> argument are appended,
- * in order, to the contents of this <tt>StringBuffer</tt>, increasing the
- * length of this <tt>StringBuffer</tt> by the length of the argument.
- * If <tt>sb</tt> is <tt>null</tt>, then the four characters
- * <tt>"null"</tt> are appended to this <tt>StringBuffer</tt>.
+ * The characters of the {@code StringBuffer} argument are appended,
+ * in order, to the contents of this {@code StringBuffer}, increasing the
+ * length of this {@code StringBuffer} by the length of the argument.
+ * If {@code sb} is {@code null}, then the four characters
+ * {@code "null"} are appended to this {@code StringBuffer}.
* <p>
* Let <i>n</i> be the length of the old character sequence, the one
- * contained in the <tt>StringBuffer</tt> just prior to execution of the
- * <tt>append</tt> method. Then the character at index <i>k</i> in
+ * contained in the {@code StringBuffer} just prior to execution of the
+ * {@code append} method. Then the character at index <i>k</i> in
* the new character sequence is equal to the character at index <i>k</i>
* in the old character sequence, if <i>k</i> is less than <i>n</i>;
* otherwise, it is equal to the character at index <i>k-n</i> in the
- * argument <code>sb</code>.
+ * argument {@code sb}.
* <p>
- * This method synchronizes on <code>this</code> (the destination)
- * object but does not synchronize on the source (<code>sb</code>).
+ * This method synchronizes on {@code this}, the destination
+ * object, but does not synchronize on the source ({@code sb}).
*
- * @param sb the <tt>StringBuffer</tt> to append.
+ * @param sb the {@code StringBuffer} to append.
* @return a reference to this object.
* @since 1.4
*/
public synchronized StringBuffer append(StringBuffer sb) {
+ toStringCache = null;
super.append(sb);
return this;
}
+ /**
+ * @since 1.8
+ */
+ @Override
+ synchronized StringBuffer append(AbstractStringBuilder asb) {
+ toStringCache = null;
+ super.append(asb);
+ return this;
+ }
/**
- * Appends the specified <code>CharSequence</code> to this
+ * Appends the specified {@code CharSequence} to this
* sequence.
* <p>
- * The characters of the <code>CharSequence</code> argument are appended,
+ * The characters of the {@code CharSequence} argument are appended,
* in order, increasing the length of this sequence by the length of the
* argument.
*
* <p>The result of this method is exactly the same as if it were an
* invocation of this.append(s, 0, s.length());
*
- * <p>This method synchronizes on this (the destination)
- * object but does not synchronize on the source (<code>s</code>).
+ * <p>This method synchronizes on {@code this}, the destination
+ * object, but does not synchronize on the source ({@code s}).
*
- * <p>If <code>s</code> is <code>null</code>, then the four characters
- * <code>"null"</code> are appended.
+ * <p>If {@code s} is {@code null}, then the four characters
+ * {@code "null"} are appended.
*
- * @param s the <code>CharSequence</code> to append.
+ * @param s the {@code CharSequence} to append.
* @return a reference to this object.
* @since 1.5
*/
- public StringBuffer append(CharSequence s) {
- // Note, synchronization achieved via other invocations
- if (s == null)
- s = "null";
- if (s instanceof String)
- return this.append((String)s);
- if (s instanceof StringBuffer)
- return this.append((StringBuffer)s);
- return this.append(s, 0, s.length());
+ @Override
+ public synchronized StringBuffer append(CharSequence s) {
+ toStringCache = null;
+ super.append(s);
+ return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @since 1.5
*/
+ @Override
public synchronized StringBuffer append(CharSequence s, int start, int end)
{
+ toStringCache = null;
super.append(s, start, end);
return this;
}
+ @Override
public synchronized StringBuffer append(char[] str) {
+ toStringCache = null;
super.append(str);
return this;
}
@@ -318,22 +363,30 @@
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized StringBuffer append(char[] str, int offset, int len) {
+ toStringCache = null;
super.append(str, offset, len);
return this;
}
+ @Override
public synchronized StringBuffer append(boolean b) {
+ toStringCache = null;
super.append(b);
return this;
}
+ @Override
public synchronized StringBuffer append(char c) {
+ toStringCache = null;
super.append(c);
return this;
}
+ @Override
public synchronized StringBuffer append(int i) {
+ toStringCache = null;
super.append(i);
return this;
}
@@ -341,22 +394,30 @@
/**
* @since 1.5
*/
+ @Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
+ toStringCache = null;
super.appendCodePoint(codePoint);
return this;
}
+ @Override
public synchronized StringBuffer append(long lng) {
+ toStringCache = null;
super.append(lng);
return this;
}
+ @Override
public synchronized StringBuffer append(float f) {
+ toStringCache = null;
super.append(f);
return this;
}
+ @Override
public synchronized StringBuffer append(double d) {
+ toStringCache = null;
super.append(d);
return this;
}
@@ -365,7 +426,9 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized StringBuffer delete(int start, int end) {
+ toStringCache = null;
super.delete(start, end);
return this;
}
@@ -374,7 +437,9 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized StringBuffer deleteCharAt(int index) {
+ toStringCache = null;
super.deleteCharAt(index);
return this;
}
@@ -383,7 +448,9 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized StringBuffer replace(int start, int end, String str) {
+ toStringCache = null;
super.replace(start, end, str);
return this;
}
@@ -392,6 +459,7 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized String substring(int start) {
return substring(start, count);
}
@@ -400,6 +468,7 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
* @since 1.4
*/
+ @Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
@@ -408,6 +477,7 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
@@ -416,9 +486,11 @@
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
+ @Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
+ toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
@@ -426,7 +498,9 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized StringBuffer insert(int offset, Object obj) {
+ toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
@@ -434,7 +508,9 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized StringBuffer insert(int offset, String str) {
+ toStringCache = null;
super.insert(offset, str);
return this;
}
@@ -442,7 +518,9 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized StringBuffer insert(int offset, char[] str) {
+ toStringCache = null;
super.insert(offset, str);
return this;
}
@@ -451,22 +529,24 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
* @since 1.5
*/
+ @Override
public StringBuffer insert(int dstOffset, CharSequence s) {
- // Note, synchronization achieved via other invocations
- if (s == null)
- s = "null";
- if (s instanceof String)
- return this.insert(dstOffset, (String)s);
- return this.insert(dstOffset, s, 0, s.length());
+ // Note, synchronization achieved via invocations of other StringBuffer methods
+ // after narrowing of s to specific type
+ // Ditto for toStringCache clearing
+ super.insert(dstOffset, s);
+ return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @since 1.5
*/
+ @Override
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
- int start, int end)
+ int start, int end)
{
+ toStringCache = null;
super.insert(dstOffset, s, start, end);
return this;
}
@@ -474,14 +554,21 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
- public StringBuffer insert(int offset, boolean b) {
- return insert(offset, String.valueOf(b));
+ @Override
+ public StringBuffer insert(int offset, boolean b) {
+ // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+ // after conversion of b to String by super class method
+ // Ditto for toStringCache clearing
+ super.insert(offset, b);
+ return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public synchronized StringBuffer insert(int offset, char c) {
+ toStringCache = null;
super.insert(offset, c);
return this;
}
@@ -489,76 +576,101 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuffer insert(int offset, int i) {
- return insert(offset, String.valueOf(i));
+ // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+ // after conversion of i to String by super class method
+ // Ditto for toStringCache clearing
+ super.insert(offset, i);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuffer insert(int offset, long l) {
- return insert(offset, String.valueOf(l));
+ // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+ // after conversion of l to String by super class method
+ // Ditto for toStringCache clearing
+ super.insert(offset, l);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuffer insert(int offset, float f) {
- return insert(offset, String.valueOf(f));
+ // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+ // after conversion of f to String by super class method
+ // Ditto for toStringCache clearing
+ super.insert(offset, f);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuffer insert(int offset, double d) {
- return insert(offset, String.valueOf(d));
+ // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+ // after conversion of d to String by super class method
+ // Ditto for toStringCache clearing
+ super.insert(offset, d);
+ return this;
}
/**
- * @throws NullPointerException {@inheritDoc}
* @since 1.4
*/
+ @Override
public int indexOf(String str) {
- return indexOf(str, 0);
+ // Note, synchronization achieved via invocations of other StringBuffer methods
+ return super.indexOf(str);
}
/**
- * @throws NullPointerException {@inheritDoc}
* @since 1.4
*/
+ @Override
public synchronized int indexOf(String str, int fromIndex) {
- return String.indexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.indexOf(str, fromIndex);
}
/**
- * @throws NullPointerException {@inheritDoc}
* @since 1.4
*/
+ @Override
public int lastIndexOf(String str) {
- // Note, synchronization achieved via other invocations
+ // Note, synchronization achieved via invocations of other StringBuffer methods
return lastIndexOf(str, count);
}
/**
- * @throws NullPointerException {@inheritDoc}
* @since 1.4
*/
+ @Override
public synchronized int lastIndexOf(String str, int fromIndex) {
- return String.lastIndexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.lastIndexOf(str, fromIndex);
}
/**
* @since JDK1.0.2
*/
+ @Override
public synchronized StringBuffer reverse() {
+ toStringCache = null;
super.reverse();
return this;
}
+ @Override
public synchronized String toString() {
- return new String(value, 0, count);
+ if (toStringCache == null) {
+ toStringCache = Arrays.copyOfRange(value, 0, count);
+ }
+ return new String(toStringCache, 0, count);
}
/**
diff --git a/ojluni/src/main/java/java/lang/StringBuilder.java b/ojluni/src/main/java/java/lang/StringBuilder.java
old mode 100755
new mode 100644
index e16522d..42642c7
--- a/ojluni/src/main/java/java/lang/StringBuilder.java
+++ b/ojluni/src/main/java/java/lang/StringBuilder.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,42 +29,46 @@
/**
* A mutable sequence of characters. This class provides an API compatible
- * with <code>StringBuffer</code>, but with no guarantee of synchronization.
+ * with {@code StringBuffer}, but with no guarantee of synchronization.
* This class is designed for use as a drop-in replacement for
- * <code>StringBuffer</code> in places where the string buffer was being
+ * {@code StringBuffer} in places where the string buffer was being
* used by a single thread (as is generally the case). Where possible,
* it is recommended that this class be used in preference to
- * <code>StringBuffer</code> as it will be faster under most implementations.
+ * {@code StringBuffer} as it will be faster under most implementations.
*
- * <p>The principal operations on a <code>StringBuilder</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * <p>The principal operations on a {@code StringBuilder} are the
+ * {@code append} and {@code insert} methods, which are
* overloaded so as to accept data of any type. Each effectively
* converts a given datum to a string and then appends or inserts the
* characters of that string to the string builder. The
- * <code>append</code> method always adds these characters at the end
- * of the builder; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the builder; the {@code insert} method adds the characters at
* a specified point.
* <p>
- * For example, if <code>z</code> refers to a string builder object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * builder to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string builder to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string builder object
+ * whose current contents are "{@code start}", then
+ * the method call {@code z.append("le")} would cause the string
+ * builder to contain "{@code startle}", whereas
+ * {@code z.insert(4, "le")} would alter the string builder to
+ * contain "{@code starlet}".
* <p>
- * In general, if sb refers to an instance of a <code>StringBuilder</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(), x)</code>.
- *
+ * In general, if sb refers to an instance of a {@code StringBuilder},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(), x)}.
+ * <p>
* Every string builder has a capacity. As long as the length of the
* character sequence contained in the string builder does not exceed
* the capacity, it is not necessary to allocate a new internal
* buffer. If the internal buffer overflows, it is automatically made larger.
*
- * <p>Instances of <code>StringBuilder</code> are not safe for
+ * <p>Instances of {@code StringBuilder} are not safe for
* use by multiple threads. If such synchronization is required then it is
* recommended that {@link java.lang.StringBuffer} be used.
*
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
* @author Michael McCloskey
* @see java.lang.StringBuffer
* @see java.lang.String
@@ -72,7 +76,7 @@
*/
public final class StringBuilder
extends AbstractStringBuilder
- implements java.io.Serializable, Appendable, CharSequence
+ implements java.io.Serializable, CharSequence
{
/** use serialVersionUID for interoperability */
@@ -88,11 +92,11 @@
/**
* Constructs a string builder with no characters in it and an
- * initial capacity specified by the <code>capacity</code> argument.
+ * initial capacity specified by the {@code capacity} argument.
*
* @param capacity the initial capacity.
- * @throws NegativeArraySizeException if the <code>capacity</code>
- * argument is less than <code>0</code>.
+ * @throws NegativeArraySizeException if the {@code capacity}
+ * argument is less than {@code 0}.
*/
public StringBuilder(int capacity) {
super(capacity);
@@ -101,10 +105,9 @@
/**
* Constructs a string builder initialized to the contents of the
* specified string. The initial capacity of the string builder is
- * <code>16</code> plus the length of the string argument.
+ * {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
- * @throws NullPointerException if <code>str</code> is <code>null</code>
*/
public StringBuilder(String str) {
super(str.length() + 16);
@@ -113,57 +116,45 @@
/**
* Constructs a string builder that contains the same characters
- * as the specified <code>CharSequence</code>. The initial capacity of
- * the string builder is <code>16</code> plus the length of the
- * <code>CharSequence</code> argument.
+ * as the specified {@code CharSequence}. The initial capacity of
+ * the string builder is {@code 16} plus the length of the
+ * {@code CharSequence} argument.
*
* @param seq the sequence to copy.
- * @throws NullPointerException if <code>seq</code> is <code>null</code>
*/
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
+ @Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
+ @Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
- // Appends the specified string builder to this sequence.
- private StringBuilder append(StringBuilder sb) {
- if (sb == null)
- return append("null");
- int len = sb.length();
- int newcount = count + len;
- if (newcount > value.length)
- expandCapacity(newcount);
- sb.getChars(0, len, value, count);
- count = newcount;
- return this;
- }
-
/**
- * Appends the specified <tt>StringBuffer</tt> to this sequence.
+ * Appends the specified {@code StringBuffer} to this sequence.
* <p>
- * The characters of the <tt>StringBuffer</tt> argument are appended,
+ * The characters of the {@code StringBuffer} argument are appended,
* in order, to this sequence, increasing the
* length of this sequence by the length of the argument.
- * If <tt>sb</tt> is <tt>null</tt>, then the four characters
- * <tt>"null"</tt> are appended to this sequence.
+ * If {@code sb} is {@code null}, then the four characters
+ * {@code "null"} are appended to this sequence.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
- * execution of the <tt>append</tt> method. Then the character at index
+ * execution of the {@code append} method. Then the character at index
* <i>k</i> in the new character sequence is equal to the character at
* index <i>k</i> in the old character sequence, if <i>k</i> is less than
* <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i>
- * in the argument <code>sb</code>.
+ * in the argument {@code sb}.
*
- * @param sb the <tt>StringBuffer</tt> to append.
+ * @param sb the {@code StringBuffer} to append.
* @return a reference to this object.
*/
public StringBuilder append(StringBuffer sb) {
@@ -171,28 +162,22 @@
return this;
}
- /**
- */
+ @Override
public StringBuilder append(CharSequence s) {
- if (s == null)
- s = "null";
- if (s instanceof String)
- return this.append((String)s);
- if (s instanceof StringBuffer)
- return this.append((StringBuffer)s);
- if (s instanceof StringBuilder)
- return this.append((StringBuilder)s);
- return this.append(s, 0, s.length());
+ super.append(s);
+ return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder append(CharSequence s, int start, int end) {
super.append(s, start, end);
return this;
}
+ @Override
public StringBuilder append(char[] str) {
super.append(str);
return this;
@@ -201,36 +186,43 @@
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder append(char[] str, int offset, int len) {
super.append(str, offset, len);
return this;
}
+ @Override
public StringBuilder append(boolean b) {
super.append(b);
return this;
}
+ @Override
public StringBuilder append(char c) {
super.append(c);
return this;
}
+ @Override
public StringBuilder append(int i) {
super.append(i);
return this;
}
+ @Override
public StringBuilder append(long lng) {
super.append(lng);
return this;
}
+ @Override
public StringBuilder append(float f) {
super.append(f);
return this;
}
+ @Override
public StringBuilder append(double d) {
super.append(d);
return this;
@@ -239,6 +231,7 @@
/**
* @since 1.5
*/
+ @Override
public StringBuilder appendCodePoint(int codePoint) {
super.appendCodePoint(codePoint);
return this;
@@ -247,6 +240,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder delete(int start, int end) {
super.delete(start, end);
return this;
@@ -255,6 +249,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder deleteCharAt(int index) {
super.deleteCharAt(index);
return this;
@@ -263,6 +258,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder replace(int start, int end, String str) {
super.replace(start, end, str);
return this;
@@ -271,6 +267,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int index, char[] str, int offset,
int len)
{
@@ -281,13 +278,16 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, Object obj) {
- return insert(offset, String.valueOf(obj));
+ super.insert(offset, obj);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, String str) {
super.insert(offset, str);
return this;
@@ -296,6 +296,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, char[] str) {
super.insert(offset, str);
return this;
@@ -304,17 +305,16 @@
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int dstOffset, CharSequence s) {
- if (s == null)
- s = "null";
- if (s instanceof String)
- return this.insert(dstOffset, (String)s);
- return this.insert(dstOffset, s, 0, s.length());
+ super.insert(dstOffset, s);
+ return this;
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int dstOffset, CharSequence s,
int start, int end)
{
@@ -325,6 +325,7 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, boolean b) {
super.insert(offset, b);
return this;
@@ -333,6 +334,7 @@
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, char c) {
super.insert(offset, c);
return this;
@@ -341,66 +343,66 @@
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, int i) {
- return insert(offset, String.valueOf(i));
+ super.insert(offset, i);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, long l) {
- return insert(offset, String.valueOf(l));
+ super.insert(offset, l);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, float f) {
- return insert(offset, String.valueOf(f));
+ super.insert(offset, f);
+ return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
+ @Override
public StringBuilder insert(int offset, double d) {
- return insert(offset, String.valueOf(d));
+ super.insert(offset, d);
+ return this;
}
- /**
- * @throws NullPointerException {@inheritDoc}
- */
+ @Override
public int indexOf(String str) {
- return indexOf(str, 0);
+ return super.indexOf(str);
}
- /**
- * @throws NullPointerException {@inheritDoc}
- */
+ @Override
public int indexOf(String str, int fromIndex) {
- return String.indexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.indexOf(str, fromIndex);
}
- /**
- * @throws NullPointerException {@inheritDoc}
- */
+ @Override
public int lastIndexOf(String str) {
- return lastIndexOf(str, count);
+ return super.lastIndexOf(str);
}
- /**
- * @throws NullPointerException {@inheritDoc}
- */
+ @Override
public int lastIndexOf(String str, int fromIndex) {
- return String.lastIndexOf(value, 0, count,
- str.toCharArray(), 0, str.length(), fromIndex);
+ return super.lastIndexOf(str, fromIndex);
}
+ @Override
public StringBuilder reverse() {
super.reverse();
return this;
}
+ @Override
public String toString() {
if (count == 0) {
return "";
@@ -409,13 +411,13 @@
}
/**
- * Save the state of the <tt>StringBuilder</tt> instance to a stream
+ * Save the state of the {@code StringBuilder} instance to a stream
* (that is, serialize it).
*
* @serialData the number of characters currently stored in the string
- * builder (<tt>int</tt>), followed by the characters in the
- * string builder (<tt>char[]</tt>). The length of the
- * <tt>char</tt> array may be greater than the number of
+ * builder ({@code int}), followed by the characters in the
+ * string builder ({@code char[]}). The length of the
+ * {@code char} array may be greater than the number of
* characters currently stored in the string builder, in which
* case extra characters are ignored.
*/
diff --git a/ojluni/src/main/java/java/util/Formatter.java b/ojluni/src/main/java/java/util/Formatter.java
index 9a4e234..ebfdd2d 100755
--- a/ojluni/src/main/java/java/util/Formatter.java
+++ b/ojluni/src/main/java/java/util/Formatter.java
@@ -3299,13 +3299,10 @@
int prec = (precision == -1 ? 6 : precision);
FormattedFloatingDecimal fd
- = new FormattedFloatingDecimal(value, prec,
+ = FormattedFloatingDecimal.valueOf(value, prec,
FormattedFloatingDecimal.Form.SCIENTIFIC);
- char[] v = new char[MAX_FD_CHARS];
- int len = fd.getChars(v);
-
- char[] mant = addZeros(mantissa(v, len), prec);
+ char[] mant = addZeros(fd.getMantissa(), prec);
// If the precision is zero and the '#' flag is set, add the
// requested decimal point.
@@ -3313,7 +3310,7 @@
mant = addDot(mant);
char[] exp = (value == 0.0)
- ? new char[] {'+','0','0'} : exponent(v, len);
+ ? new char[] {'+','0','0'} : fd.getExponent();
int newW = width;
if (width != -1)
@@ -3340,15 +3337,10 @@
int prec = (precision == -1 ? 6 : precision);
FormattedFloatingDecimal fd
- = new FormattedFloatingDecimal(value, prec,
- FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
+ = FormattedFloatingDecimal.valueOf(value, prec,
+ FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
- // MAX_FD_CHARS + 1 (round?)
- char[] v = new char[MAX_FD_CHARS + 1
- + Math.abs(fd.getExponent())];
- int len = fd.getChars(v);
-
- char[] mant = addZeros(mantissa(v, len), prec);
+ char[] mant = addZeros(fd.getMantissa(), prec);
// If the precision is zero and the '#' flag is set, add the
// requested decimal point.
@@ -3366,23 +3358,29 @@
else if (precision == 0)
prec = 1;
- FormattedFloatingDecimal fd
- = new FormattedFloatingDecimal(value, prec,
- FormattedFloatingDecimal.Form.GENERAL);
+ char[] exp;
+ char[] mant;
+ int expRounded;
+ if (value == 0.0) {
+ exp = null;
+ mant = new char[] {'0'};
+ expRounded = 0;
+ } else {
+ FormattedFloatingDecimal fd
+ = FormattedFloatingDecimal.valueOf(value, prec,
+ FormattedFloatingDecimal.Form.GENERAL);
+ exp = fd.getExponent();
+ mant = fd.getMantissa();
+ expRounded = fd.getExponentRounded();
+ }
- // MAX_FD_CHARS + 1 (round?)
- char[] v = new char[MAX_FD_CHARS + 1
- + Math.abs(fd.getExponent())];
- int len = fd.getChars(v);
-
- char[] exp = exponent(v, len);
if (exp != null) {
prec -= 1;
} else {
- prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1;
+ prec -= expRounded + 1;
}
- char[] mant = addZeros(mantissa(v, len), prec);
+ mant = addZeros(mant, prec);
// If the precision is zero and the '#' flag is set, add the
// requested decimal point.
if (f.contains(Flags.ALTERNATE) && (prec == 0))
diff --git a/ojluni/src/main/java/sun/misc/FDBigInteger.java b/ojluni/src/main/java/sun/misc/FDBigInteger.java
new file mode 100644
index 0000000..77d6fbc
--- /dev/null
+++ b/ojluni/src/main/java/sun/misc/FDBigInteger.java
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.misc;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+ //
+ // This class contains many comments that start with "/*@" mark.
+ // They are behavourial specification in
+ // the Java Modelling Language (JML):
+ // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+ //
+
+ /*@
+ @ public pure model static \bigint UNSIGNED(int v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 32);
+ @ }
+ @
+ @ public pure model static \bigint UNSIGNED(long v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 64);
+ @ }
+ @
+ @ public pure model static \bigint AP(int[] data, int len) {
+ @ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+ @ }
+ @
+ @ public pure model static \bigint pow52(int p5, int p2) {
+ @ ghost \bigint v = 1;
+ @ for (int i = 0; i < p5; i++) v *= 5;
+ @ return v << p2;
+ @ }
+ @
+ @ public pure model static \bigint pow10(int p10) {
+ @ return pow52(p10, p10);
+ @ }
+ @*/
+
+ static final int[] SMALL_5_POW = {
+ 1,
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+
+ static final long[] LONG_5_POW = {
+ 1L,
+ 5L,
+ 5L * 5,
+ 5L * 5 * 5,
+ 5L * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ };
+
+ // Maximum size of cache of powers of 5 as FDBigIntegers.
+ private static final int MAX_FIVE_POW = 340;
+
+ // Cache of big powers of 5 as FDBigIntegers.
+ private static final FDBigInteger POW_5_CACHE[];
+
+ // Initialize FDBigInteger cache of powers of 5.
+ static {
+ POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+ int i = 0;
+ while (i < SMALL_5_POW.length) {
+ FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+ pow5.makeImmutable();
+ POW_5_CACHE[i] = pow5;
+ i++;
+ }
+ FDBigInteger prev = POW_5_CACHE[i - 1];
+ while (i < MAX_FIVE_POW) {
+ POW_5_CACHE[i] = prev = prev.mult(5);
+ prev.makeImmutable();
+ i++;
+ }
+ }
+
+ // Zero as an FDBigInteger.
+ public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+ // Ensure ZERO is immutable.
+ static {
+ ZERO.makeImmutable();
+ }
+
+ // Constant for casting an int to a long via bitwise AND.
+ private final static long LONG_MASK = 0xffffffffL;
+
+ //@ spec_public non_null;
+ private int data[]; // value: data[0] is least significant
+ //@ spec_public;
+ private int offset; // number of least significant zero padding ints
+ //@ spec_public;
+ private int nWords; // data[nWords-1]!=0, all values above are zero
+ // if nWords==0 -> this FDBigInteger is zero
+ //@ spec_public;
+ private boolean isImmutable = false;
+
+ /*@
+ @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ public invariant nWords == 0 ==> offset == 0;
+ @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+ @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+ @ public pure model \bigint value() {
+ @ return AP(data, nWords) << (offset*32);
+ @ }
+ @*/
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from data and padding. The
+ * <code>data</code> parameter has the least significant <code>int</code> at
+ * the zeroth index. The <code>offset</code> parameter gives the number of
+ * zero <code>int</code>s to be inferred below the least significant element
+ * of <code>data</code>.
+ *
+ * @param data An array containing all non-zero <code>int</code>s of the value.
+ * @param offset An offset indicating the number of zero <code>int</code>s to pad
+ * below the least significant element of <code>data</code>.
+ */
+ /*@
+ @ requires data != null && offset >= 0;
+ @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+ @ ensures this.data == \old(data);
+ @*/
+ private FDBigInteger(int[] data, int offset) {
+ this.data = data;
+ this.offset = offset;
+ this.nWords = data.length;
+ trimLeadingZeros();
+ }
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from a starting value and some
+ * decimal digits.
+ *
+ * @param lValue The starting value.
+ * @param digits The decimal digits.
+ * @param kDigits The initial index into <code>digits</code>.
+ * @param nDigits The final index into <code>digits</code>.
+ */
+ /*@
+ @ requires digits != null;
+ @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+ @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+ @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+ @*/
+ public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+ int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
+ data = new int[n]; // allocate enough space
+ data[0] = (int) lValue; // starting value
+ data[1] = (int) (lValue >>> 32);
+ offset = 0;
+ nWords = 2;
+ int i = kDigits;
+ int limit = nDigits - 5; // slurp digits 5 at a time.
+ int v;
+ while (i < limit) {
+ int ilim = i + 5;
+ v = (int) digits[i++] - (int) '0';
+ while (i < ilim) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ }
+ multAddMe(100000, v); // ... where 100000 is 10^5.
+ }
+ int factor = 1;
+ v = 0;
+ while (i < nDigits) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ factor *= 10;
+ }
+ if (factor != 1) {
+ multAddMe(factor, v);
+ }
+ trimLeadingZeros();
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfPow52(int p5, int p2) {
+ if (p5 != 0) {
+ if (p2 == 0) {
+ return big5pow(p5);
+ } else if (p5 < SMALL_5_POW.length) {
+ int pow5 = SMALL_5_POW[p5];
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{pow5}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ pow5 << bitcount,
+ pow5 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ return big5pow(p5).leftShift(p2);
+ }
+ } else {
+ return valueOfPow2(p2);
+ }
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param value The constant factor.
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+ assert p5 >= 0 : p5;
+ assert p2 >= 0 : p2;
+ int v0 = (int) value;
+ int v1 = (int) (value >>> 32);
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (p5 != 0) {
+ if (p5 < SMALL_5_POW.length) {
+ long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+ long carry = (v0 & LONG_MASK) * pow5;
+ v0 = (int) carry;
+ carry >>>= 32;
+ carry = (v1 & LONG_MASK) * pow5 + carry;
+ v1 = (int) carry;
+ int v2 = (int) (carry >>> 32);
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+ v2 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ int[] r;
+ if (v1 == 0) {
+ r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, r);
+ } else {
+ r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, v1, r);
+ }
+ return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+ }
+ } else if (p2 != 0) {
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ v1 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ }
+ return new FDBigInteger(new int[]{v0, v1}, 0);
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>2<sup>p2</sup></code>.
+ *
+ * @param p2 The exponent of 2.
+ * @return <code>2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == pow52(0, p2);
+ @*/
+ private static FDBigInteger valueOfPow2(int p2) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+ }
+
+ /**
+ * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+ * the offset and number of non-zero leading words accordingly.
+ */
+ /*@
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires nWords == 0 ==> offset == 0;
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ private /*@ helper @*/ void trimLeadingZeros() {
+ int i = nWords;
+ if (i > 0 && (data[--i] == 0)) {
+ //for (; i > 0 && data[i - 1] == 0; i--) ;
+ while(i > 0 && data[i - 1] == 0) {
+ i--;
+ }
+ this.nWords = i;
+ if (i == 0) { // all words are zero
+ this.offset = 0;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+ * normalization bias is a left shift such that after it the highest word
+ * of the value will have the 4 highest bits equal to zero:
+ * <code>(highestWord & 0xf0000000) == 0</code>, but the next bit should be 1
+ * <code>(highestWord & 0x08000000) != 0</code>.
+ *
+ * @return The normalization bias.
+ */
+ /*@
+ @ requires this.value() > 0;
+ @*/
+ public /*@ pure @*/ int getNormalizationBias() {
+ if (nWords == 0) {
+ throw new IllegalArgumentException("Zero value cannot be normalized");
+ }
+ int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+ return (zeros < 4) ? 28 + zeros : zeros - 4;
+ }
+
+ // TODO: Why is anticount param needed if it is always 32 - bitcount?
+ /**
+ * Left shifts the contents of one int array into another.
+ *
+ * @param src The source array.
+ * @param idx The initial index of the source array.
+ * @param result The destination array.
+ * @param bitcount The left shift.
+ * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+ * @param prev The prior source value.
+ */
+ /*@
+ @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+ @ requires src.length >= idx && result.length > idx;
+ @ assignable result[*];
+ @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+ @*/
+ private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+ for (; idx > 0; idx--) {
+ int v = (prev << bitcount);
+ prev = src[idx - 1];
+ v |= (prev >>> anticount);
+ result[idx] = v;
+ }
+ int v = prev << bitcount;
+ result[0] = v;
+ }
+
+ /**
+ * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+ * in-place unless the <code>FDBigInteger</code> is immutable in which case
+ * a new instance of <code>FDBigInteger</code> is returned.
+ *
+ * @param shift The number of bits to shift left.
+ * @return The shifted <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0 || shift == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @*/
+ public FDBigInteger leftShift(int shift) {
+ if (shift == 0 || nWords == 0) {
+ return this;
+ }
+ int wordcount = shift >> 5;
+ int bitcount = shift & 0x1f;
+ if (this.isImmutable) {
+ if (bitcount == 0) {
+ return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+ } else {
+ int anticount = 32 - bitcount;
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result;
+ if (hi != 0) {
+ result = new int[nWords + 1];
+ result[nWords] = hi;
+ } else {
+ result = new int[nWords];
+ }
+ leftShift(data,idx,result,bitcount,anticount,prev);
+ return new FDBigInteger(result, offset + wordcount);
+ }
+ } else {
+ if (bitcount != 0) {
+ int anticount = 32 - bitcount;
+ if ((data[0] << bitcount) == 0) {
+ int idx = 0;
+ int prev = data[idx];
+ for (; idx < nWords - 1; idx++) {
+ int v = (prev >>> anticount);
+ prev = data[idx + 1];
+ v |= (prev << bitcount);
+ data[idx] = v;
+ }
+ int v = prev >>> anticount;
+ data[idx] = v;
+ if(v==0) {
+ nWords--;
+ }
+ offset++;
+ } else {
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result = data;
+ int[] src = data;
+ if (hi != 0) {
+ if(nWords == data.length) {
+ data = result = new int[nWords + 1];
+ }
+ result[nWords++] = hi;
+ }
+ leftShift(src,idx,result,bitcount,anticount,prev);
+ }
+ }
+ offset += wordcount;
+ return this;
+ }
+ }
+
+ /**
+ * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+ *
+ * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ ensures \result == 0;
+ @
+ @ also
+ @
+ @ requires this.value() > 0;
+ @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+ @*/
+ private /*@ pure @*/ int size() {
+ return nWords + offset;
+ }
+
+
+ /**
+ * Computes
+ * <pre>
+ * q = (int)( this / S )
+ * this = 10 * ( this mod S )
+ * Return q.
+ * </pre>
+ * This is the iteration step of digit development for output.
+ * We assume that S has been normalized, as above, and that
+ * "this" has been left-shifted accordingly.
+ * Also assumed, of course, is that the result, q, can be expressed
+ * as an integer, 0 <= q < 10.
+ *
+ * @param The divisor of this <code>FDBigInteger</code>.
+ * @return <code>q = (int)(this / S)</code>.
+ */
+ /*@
+ @ requires !this.isImmutable;
+ @ requires this.size() <= S.size();
+ @ requires this.data.length + this.offset >= S.size();
+ @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == \old(this.value() / S.value());
+ @ ensures this.value() == \old(10 * (this.value() % S.value()));
+ @*/
+ public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+ assert !this.isImmutable : "cannot modify immutable value";
+ // ensure that this and S have the same number of
+ // digits. If S is properly normalized and q < 10 then
+ // this must be so.
+ int thSize = this.size();
+ int sSize = S.size();
+ if (thSize < sSize) {
+ // this value is significantly less than S, result of division is zero.
+ // just mult this by 10.
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if(p!=0) {
+ this.data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return 0;
+ } else if (thSize > sSize) {
+ throw new IllegalArgumentException("disparate values");
+ }
+ // estimate q the obvious way. We will usually be
+ // right. If not, then we're only off by a little and
+ // will re-add.
+ long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+ long diff = multDiffMe(q, S);
+ if (diff != 0L) {
+ //@ assert q != 0;
+ //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+ //@ assert this.offset <= S.offset;
+
+ // q is too big.
+ // add S back in until this turns +. This should
+ // not be very many times!
+ long sum = 0L;
+ int tStart = S.offset - this.offset;
+ //@ assert tStart >= 0;
+ int[] sd = S.data;
+ int[] td = this.data;
+ while (sum == 0L) {
+ for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+ sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) sum;
+ sum >>>= 32; // Signed or unsigned, answer is 0 or 1
+ }
+ //
+ // Originally the following line read
+ // "if ( sum !=0 && sum != -1 )"
+ // but that would be wrong, because of the
+ // treatment of the two values as entirely unsigned,
+ // it would be impossible for a carry-out to be interpreted
+ // as -1 -- it would have to be a single-bit carry-out, or +1.
+ //
+ assert sum == 0 || sum == 1 : sum; // carry out of division correction
+ q -= 1;
+ }
+ }
+ // finally, we can multiply this by 10.
+ // it cannot overflow, right, as the high-order word has
+ // at least 4 high-order zeros!
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ assert p == 0 : p; // Carry out of *10
+ trimLeadingZeros();
+ return (int) q;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+ * performed in place unless the <code>FDBigInteger</code> is immutable in
+ * which case a new <code>FDBigInteger</code> will be returned.
+ *
+ * @return The <code>FDBigInteger</code> multiplied by 10.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @*/
+ public FDBigInteger multBy10() {
+ if (nWords == 0) {
+ return this;
+ }
+ if (isImmutable) {
+ int[] res = new int[nWords + 1];
+ res[nWords] = multAndCarryBy10(data, nWords, res);
+ return new FDBigInteger(res, offset);
+ } else {
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if (p != 0) {
+ if (nWords == data.length) {
+ if (data[0] == 0) {
+ System.arraycopy(data, 1, data, 0, --nWords);
+ offset++;
+ } else {
+ data = Arrays.copyOf(data, data.length + 1);
+ }
+ }
+ data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return this;
+ }
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+ * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+ * will be returned.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return
+ */
+ /*@
+ @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @*/
+ public FDBigInteger multByPow52(int p5, int p2) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ FDBigInteger res = this;
+ if (p5 != 0) {
+ int[] r;
+ int extraSize = (p2 != 0) ? 1 : 0;
+ if (p5 < SMALL_5_POW.length) {
+ r = new int[this.nWords + 1 + extraSize];
+ mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+ res = new FDBigInteger(r, this.offset);
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ r = new int[this.nWords + pow5.size() + extraSize];
+ mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+ res = new FDBigInteger(r, this.offset + pow5.offset);
+ }
+ }
+ return res.leftShift(p2);
+ }
+
+ /**
+ * Multiplies two big integers represented as int arrays.
+ *
+ * @param s1 The first array factor.
+ * @param s1Len The number of elements of <code>s1</code> to use.
+ * @param s2 The second array factor.
+ * @param s2Len The number of elements of <code>s2</code> to use.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires s1 != dst && s2 != dst;
+ @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+ @ assignable dst[0 .. s1Len + s2Len - 1];
+ @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+ @*/
+ private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+ for (int i = 0; i < s1Len; i++) {
+ long v = s1[i] & LONG_MASK;
+ long p = 0L;
+ for (int j = 0; j < s2Len; j++) {
+ p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+ dst[i + j] = (int) p;
+ p >>>= 32;
+ }
+ dst[i + s2Len] = (int) p;
+ }
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the subtrahend is immutable, store the result in this(minuend).
+ * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires this.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend;
+ if (this.isImmutable) {
+ minuend = new FDBigInteger(this.data.clone(), this.offset);
+ } else {
+ minuend = this;
+ }
+ int offsetDiff = subtrahend.offset - minuend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ // need to expand minuend
+ int rLen = minLen - offsetDiff;
+ if (rLen < mData.length) {
+ System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+ Arrays.fill(mData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+ minuend.data = mData = r;
+ }
+ minuend.offset = subtrahend.offset;
+ minuend.nWords = minLen = rLen;
+ offsetDiff = 0;
+ }
+ long borrow = 0L;
+ int mIndex = offsetDiff;
+ for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ for (; borrow != 0 && mIndex < minLen; mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ minuend.trimLeadingZeros();
+ return minuend;
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the this(minuend) is immutable, store the result in subtrahend.
+ * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+ @ ensures \result == subtrahend;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend = this;
+ if (subtrahend.isImmutable) {
+ subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+ }
+ int offsetDiff = minuend.offset - subtrahend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ int rLen = minLen;
+ if (rLen < sData.length) {
+ System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+ Arrays.fill(sData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+ subtrahend.data = sData = r;
+ }
+ subtrahend.offset = minuend.offset;
+ subLen -= offsetDiff;
+ offsetDiff = 0;
+ } else {
+ int rLen = minLen + offsetDiff;
+ if (rLen >= sData.length) {
+ subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+ }
+ }
+ //@ assert minuend == this && minuend.value() == \old(this.value());
+ //@ assert mData == minuend.data && minLen == minuend.nWords;
+ //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+ //@ assert sData == subtrahend.data;
+ //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+ //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+ //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+ //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+ int sIndex = 0;
+ long borrow = 0L;
+ for (; sIndex < offsetDiff; sIndex++) {
+ long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ //@ assert sIndex == offsetDiff;
+ for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+ //@ assert sIndex == offsetDiff + mIndex;
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ subtrahend.nWords = sIndex;
+ subtrahend.trimLeadingZeros();
+ return subtrahend;
+
+ }
+
+ /**
+ * Determines whether all elements of an array are zero for all indices less
+ * than a given index.
+ *
+ * @param a The array to be examined.
+ * @param from The index strictly below which elements are to be examined.
+ * @return Zero if all elements in range are zero, 1 otherwise.
+ */
+ /*@
+ @ requires 0 <= from && from <= a.length;
+ @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+ @*/
+ private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+ while (from > 0) {
+ if (a[--from] != 0) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+ * integer accordingly as:
+ * <pre>
+ * >0: this > other
+ * 0: this == other
+ * <0: this < other
+ * </pre>
+ *
+ * @param other The <code>FDBigInteger</code> to compare.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmp(FDBigInteger other) {
+ int aSize = nWords + offset;
+ int bSize = other.nWords + other.offset;
+ if (aSize > bSize) {
+ return 1;
+ } else if (aSize < bSize) {
+ return -1;
+ }
+ int aLen = nWords;
+ int bLen = other.nWords;
+ while (aLen > 0 && bLen > 0) {
+ int a = data[--aLen];
+ int b = other.data[--bLen];
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ }
+ if (aLen > 0) {
+ return checkZeroTail(data, aLen);
+ }
+ if (bLen > 0) {
+ return -checkZeroTail(other.data, bLen);
+ }
+ return 0;
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ * Returns an integer accordingly as:
+ * <pre>
+ * >0: this > other
+ * 0: this == other
+ * <0: this < other
+ * </pre>
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+ if (p5 == 0) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ int size = this.nWords + this.offset;
+ if (size > wordcount + 1) {
+ return 1;
+ } else if (size < wordcount + 1) {
+ return -1;
+ }
+ int a = this.data[this.nWords -1];
+ int b = 1 << bitcount;
+ if (a != b) {
+ return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ return checkZeroTail(this.data, this.nWords - 1);
+ }
+ return this.cmp(big5pow(p5).leftShift(p2));
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+ * value according to the comparison as:
+ * <pre>
+ * -1: this < x + y
+ * 0: this == x + y
+ * 1: this > x + y
+ * </pre>
+ * @param x The first addend of the sum to compare.
+ * @param y The second addend of the sum to compare.
+ * @return -1, 0, or 1 according to the result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+ FDBigInteger big;
+ FDBigInteger small;
+ int xSize = x.size();
+ int ySize = y.size();
+ int bSize;
+ int sSize;
+ if (xSize >= ySize) {
+ big = x;
+ small = y;
+ bSize = xSize;
+ sSize = ySize;
+ } else {
+ big = y;
+ small = x;
+ bSize = ySize;
+ sSize = xSize;
+ }
+ int thSize = this.size();
+ if (bSize == 0) {
+ return thSize == 0 ? 0 : 1;
+ }
+ if (sSize == 0) {
+ return this.cmp(big);
+ }
+ if (bSize > thSize) {
+ return -1;
+ }
+ if (bSize + 1 < thSize) {
+ return 1;
+ }
+ long top = (big.data[big.nWords - 1] & LONG_MASK);
+ if (sSize == bSize) {
+ top += (small.data[small.nWords - 1] & LONG_MASK);
+ }
+ if ((top >>> 32) == 0) {
+ if (((top + 1) >>> 32) == 0) {
+ // good case - no carry extension
+ if (bSize < thSize) {
+ return 1;
+ }
+ // here sum.nWords == this.nWords
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ } else { // (top>>>32)!=0 guaranteed carry extension
+ if (bSize + 1 > thSize) {
+ return -1;
+ }
+ // here sum.nWords == this.nWords
+ top >>>= 32;
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ return this.cmp(big.add(small));
+ }
+
+ /**
+ * Makes this <code>FDBigInteger</code> immutable.
+ */
+ /*@
+ @ assignable this.isImmutable;
+ @ ensures this.isImmutable;
+ @*/
+ public void makeImmutable() {
+ this.isImmutable = true;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by an integer.
+ *
+ * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+ * @return This <code>FDBigInteger</code> multiplied by an integer.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+ @*/
+ private FDBigInteger mult(int i) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ int[] r = new int[nWords + 1];
+ mult(data, nWords, i, r);
+ return new FDBigInteger(r, offset);
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> factor by which to multiply.
+ * @return The product of this and the parameter <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == other;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * other.value());
+ @*/
+ private FDBigInteger mult(FDBigInteger other) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ if (this.size() == 1) {
+ return other.mult(data[0]);
+ }
+ if (other.nWords == 0) {
+ return other;
+ }
+ if (other.size() == 1) {
+ return this.mult(other.data[0]);
+ }
+ int[] r = new int[nWords + other.nWords];
+ mult(this.data, this.nWords, other.data, other.nWords, r);
+ return new FDBigInteger(r, this.offset + other.offset);
+ }
+
+ /**
+ * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> to add.
+ * @return The sum of the <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() + other.value());
+ @*/
+ private FDBigInteger add(FDBigInteger other) {
+ FDBigInteger big, small;
+ int bigLen, smallLen;
+ int tSize = this.size();
+ int oSize = other.size();
+ if (tSize >= oSize) {
+ big = this;
+ bigLen = tSize;
+ small = other;
+ smallLen = oSize;
+ } else {
+ big = other;
+ bigLen = oSize;
+ small = this;
+ smallLen = tSize;
+ }
+ int[] r = new int[bigLen + 1];
+ int i = 0;
+ long carry = 0L;
+ for (; i < smallLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+ + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ for (; i < bigLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ r[bigLen] = (int) carry;
+ return new FDBigInteger(r, 0);
+ }
+
+
+ /**
+ * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+ * result is computed in place. This method is intended only to be invoked
+ * from
+ * <code>
+ * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+ * </code>.
+ *
+ * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+ * @param addend The value to add to the product of this
+ * <code>FDBigInteger</code> and <code>iv</code>.
+ */
+ /*@
+ @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+ @ assignable this.data[*];
+ @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+ @*/
+ private /*@ helper @*/ void multAddMe(int iv, int addend) {
+ long v = iv & LONG_MASK;
+ // unroll 0th iteration, doing addition.
+ long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+ data[0] = (int) p;
+ p >>>= 32;
+ for (int i = 1; i < nWords; i++) {
+ p += v * (data[i] & LONG_MASK);
+ data[i] = (int) p;
+ p >>>= 32;
+ }
+ if (p != 0L) {
+ data[nWords++] = (int) p; // will fail noisily if illegal!
+ }
+ }
+
+ //
+ // original doc:
+ //
+ // do this -=q*S
+ // returns borrow
+ //
+ /**
+ * Multiplies the parameters and subtracts them from this
+ * <code>FDBigInteger</code>.
+ *
+ * @param q The integer parameter.
+ * @param S The <code>FDBigInteger</code> parameter.
+ * @return <code>this - q*S</code>.
+ */
+ /*@
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ /*@
+ @ requires 0 < q && q <= (1L << 31);
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires !this.isImmutable;
+ @ requires this.size() == S.size();
+ @ requires this != S;
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures -q <= \result && \result <= 0;
+ @ ensures this.size() == \old(this.size());
+ @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+ @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+ @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+ @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+ @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+ @
+ @ also
+ @
+ @ requires q == 0;
+ @ assignable \nothing;
+ @ ensures \result == 0;
+ @*/
+ private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+ long diff = 0L;
+ if (q != 0) {
+ int deltaSize = S.offset - this.offset;
+ if (deltaSize >= 0) {
+ int[] sd = S.data;
+ int[] td = this.data;
+ for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ } else {
+ deltaSize = -deltaSize;
+ int[] rd = new int[nWords + deltaSize];
+ int sIndex = 0;
+ int rIndex = 0;
+ int[] sd = S.data;
+ for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+ diff -= q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ int tIndex = 0;
+ int[] td = this.data;
+ for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ this.nWords += deltaSize;
+ this.offset -= deltaSize;
+ this.data = rd;
+ }
+ }
+ return diff;
+ }
+
+
+ /**
+ * Multiplies by 10 a big integer represented as an array. The final carry
+ * is returned.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param dst The product array.
+ * @return The final carry of the multiplication.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen;
+ @ assignable dst[0 .. srcLen - 1];
+ @ ensures 0 <= \result && \result < 10;
+ @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+ @*/
+ private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * 10L + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ return (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is an <code>int</code>.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param value The constant factor by which to multiply.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+ @ assignable dst[0 .. srcLen];
+ @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+ @*/
+ private static void mult(int[] src, int srcLen, int value, int[] dst) {
+ long val = value & LONG_MASK;
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * val + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is a long represent as two <code>int</code>s.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param v0 The lower 32 bits of the long factor.
+ * @param v1 The upper 32 bits of the long factor.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src != dst;
+ @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+ @ assignable dst[0 .. srcLen + 1];
+ @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+ @*/
+ private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+ long v = v0 & LONG_MASK;
+ long carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = v * (src[j] & LONG_MASK) + carry;
+ dst[j] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ v = v1 & LONG_MASK;
+ carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+ dst[j + 1] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen + 1] = (int) carry;
+ }
+
+ // Fails assertion for negative exponent.
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5pow(int p) {
+ assert p >= 0 : p; // negative power of 5
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ return big5powRec(p);
+ }
+
+ // slow path
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5powRec(int p) {
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ FDBigInteger bigq = big5powRec(q);
+ if (r < SMALL_5_POW.length) {
+ return bigq.mult(SMALL_5_POW[r]);
+ } else {
+ return bigq.mult(big5powRec(r));
+ }
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+ *
+ * @return The hexadecimal string representation.
+ */
+ public String toHexString(){
+ if(nWords ==0) {
+ return "0";
+ }
+ StringBuilder sb = new StringBuilder((nWords +offset)*8);
+ for(int i= nWords -1; i>=0; i--) {
+ String subStr = Integer.toHexString(data[i]);
+ for(int j = subStr.length(); j<8; j++) {
+ sb.append('0');
+ }
+ sb.append(subStr);
+ }
+ for(int i=offset; i>0; i--) {
+ sb.append("00000000");
+ }
+ return sb.toString();
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+ *
+ * @return The <code>BigInteger</code> representation.
+ */
+ public BigInteger toBigInteger() {
+ byte[] magnitude = new byte[nWords * 4 + 1];
+ for (int i = 0; i < nWords; i++) {
+ int w = data[i];
+ magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+ magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+ magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+ magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+ }
+ return new BigInteger(magnitude).shiftLeft(offset * 32);
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a string.
+ *
+ * @return The string representation.
+ */
+ @Override
+ public String toString(){
+ return toBigInteger().toString();
+ }
+}
diff --git a/ojluni/src/main/java/sun/misc/FloatingDecimal.java b/ojluni/src/main/java/sun/misc/FloatingDecimal.java
new file mode 100644
index 0000000..ddd8790
--- /dev/null
+++ b/ojluni/src/main/java/sun/misc/FloatingDecimal.java
@@ -0,0 +1,2541 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.util.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+ //
+ // Constants of the implementation;
+ // most are IEEE-754 related.
+ // (There are more really boring constants at the end.)
+ //
+ static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+ static final long FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+ static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+ static final int MAX_SMALL_BIN_EXP = 62;
+ static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
+ static final int MAX_DECIMAL_DIGITS = 15;
+ static final int MAX_DECIMAL_EXPONENT = 308;
+ static final int MIN_DECIMAL_EXPONENT = -324;
+ static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+ static final int MAX_NDIGITS = 1100;
+
+ static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
+ static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
+ static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
+ static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
+ static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
+ static final int SINGLE_MAX_NDIGITS = 200;
+
+ static final int INT_DECIMAL_DIGITS = 9;
+
+ /**
+ * Converts a double precision floating point value to a <code>String</code>.
+ *
+ * @param d The double precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(double d) {
+ return getBinaryToASCIIConverter(d).toJavaFormatString();
+ }
+
+ /**
+ * Converts a single precision floating point value to a <code>String</code>.
+ *
+ * @param f The single precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(float f) {
+ return getBinaryToASCIIConverter(f).toJavaFormatString();
+ }
+
+ /**
+ * Appends a double precision floating point value to an <code>Appendable</code>.
+ * @param d The double precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(double d, Appendable buf) {
+ getBinaryToASCIIConverter(d).appendTo(buf);
+ }
+
+ /**
+ * Appends a single precision floating point value to an <code>Appendable</code>.
+ * @param f The single precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(float f, Appendable buf) {
+ getBinaryToASCIIConverter(f).appendTo(buf);
+ }
+
+ /**
+ * Converts a <code>String</code> to a double precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The double precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted double precision value.
+ */
+ public static double parseDouble(String s) throws NumberFormatException {
+ return readJavaFormatString(s).doubleValue();
+ }
+
+ /**
+ * Converts a <code>String</code> to a single precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The single precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted single precision value.
+ */
+ public static float parseFloat(String s) throws NumberFormatException {
+ return readJavaFormatString(s).floatValue();
+ }
+
+ /**
+ * A converter which can process single or double precision floating point
+ * values into an ASCII <code>String</code> representation.
+ */
+ public interface BinaryToASCIIConverter {
+ /**
+ * Converts a floating point value into an ASCII <code>String</code>.
+ * @return The value converted to a <code>String</code>.
+ */
+ public String toJavaFormatString();
+
+ /**
+ * Appends a floating point value to an <code>Appendable</code>.
+ * @param buf The <code>Appendable</code> to receive the value.
+ */
+ public void appendTo(Appendable buf);
+
+ /**
+ * Retrieves the decimal exponent most closely corresponding to this value.
+ * @return The decimal exponent.
+ */
+ public int getDecimalExponent();
+
+ /**
+ * Retrieves the value as an array of digits.
+ * @param digits The digit array.
+ * @return The number of valid digits copied into the array.
+ */
+ public int getDigits(char[] digits);
+
+ /**
+ * Indicates the sign of the value.
+ * @return <code>value < 0.0</code>.
+ */
+ public boolean isNegative();
+
+ /**
+ * Indicates whether the value is either infinite or not a number.
+ *
+ * @return <code>true</code> if and only if the value is <code>NaN</code>
+ * or infinite.
+ */
+ public boolean isExceptional();
+
+ /**
+ * Indicates whether the value was rounded up during the binary to ASCII
+ * conversion.
+ *
+ * @return <code>true</code> if and only if the value was rounded up.
+ */
+ public boolean digitsRoundedUp();
+
+ /**
+ * Indicates whether the binary to ASCII conversion was exact.
+ *
+ * @return <code>true</code> if any only if the conversion was exact.
+ */
+ public boolean decimalDigitsExact();
+ }
+
+ /**
+ * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+ * and infinite values.
+ */
+ private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ final private String image;
+ private boolean isNegative;
+
+ public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+ this.image = image;
+ this.isNegative = isNegative;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ return image;
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(image);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(image);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ throw new IllegalArgumentException("Exceptional value does not have an exponent");
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ throw new IllegalArgumentException("Exceptional value does not have digits");
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return true;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ throw new IllegalArgumentException("Exceptional value is not rounded");
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ throw new IllegalArgumentException("Exceptional value is not exact");
+ }
+ }
+
+ private static final String INFINITY_REP = "Infinity";
+ private static final int INFINITY_LENGTH = INFINITY_REP.length();
+ private static final String NAN_REP = "NaN";
+ private static final int NAN_LENGTH = NAN_REP.length();
+
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+ private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
+
+ /**
+ * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+ */
+ static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ private boolean isNegative;
+ private int decExponent;
+ private int firstDigitIndex;
+ private int nDigits;
+ private final char[] digits;
+ private final char[] buffer = new char[26];
+
+ //
+ // The fields below provide additional information about the result of
+ // the binary to decimal digits conversion done in dtoa() and roundup()
+ // methods. They are changed if needed by those two methods.
+ //
+
+ // True if the dtoa() binary to decimal conversion was exact.
+ private boolean exactDecimalConversion = false;
+
+ // True if the result of the binary to decimal conversion was rounded-up
+ // at the end of the conversion process, i.e. roundUp() method was called.
+ private boolean decimalDigitsRoundedUp = false;
+
+ /**
+ * Default constructor; used for non-zero values,
+ * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+ */
+ BinaryToASCIIBuffer(){
+ this.digits = new char[20];
+ }
+
+ /**
+ * Creates a specialized value (positive and negative zeros).
+ */
+ BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+ this.isNegative = isNegative;
+ this.decExponent = 0;
+ this.digits = digits;
+ this.firstDigitIndex = 0;
+ this.nDigits = digits.length;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ int len = getChars(buffer);
+ return new String(buffer, 0, len);
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ int len = getChars(buffer);
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(buffer, 0, len);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(buffer, 0, len);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ return decExponent;
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+ return this.nDigits;
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return false;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ return decimalDigitsRoundedUp;
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ return exactDecimalConversion;
+ }
+
+ private void setSign(boolean isNegative) {
+ this.isNegative = isNegative;
+ }
+
+ /**
+ * This is the easy subcase --
+ * all the significant bits, after scaling, are held in lvalue.
+ * negSign and decExponent tell us what processing and scaling
+ * has already been done. Exceptional cases have already been
+ * stripped out.
+ * In particular:
+ * lvalue is a finite number (not Inf, nor NaN)
+ * lvalue > 0L (not zero, nor negative).
+ *
+ * The only reason that we develop the digits here, rather than
+ * calling on Long.toString() is that we can do it a little faster,
+ * and besides want to treat trailing 0s specially. If Long.toString
+ * changes, we should re-evaluate this strategy!
+ */
+ private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
+ if ( insignificantDigits != 0 ){
+ // Discard non-significant low-order bits, while rounding,
+ // up to insignificant value.
+ long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+ long residue = lvalue % pow10;
+ lvalue /= pow10;
+ decExponent += insignificantDigits;
+ if ( residue >= (pow10>>1) ){
+ // round up based on the low-order bits we're discarding
+ lvalue++;
+ }
+ }
+ int digitno = digits.length -1;
+ int c;
+ if ( lvalue <= Integer.MAX_VALUE ){
+ assert lvalue > 0L : lvalue; // lvalue <= 0
+ // even easier subcase!
+ // can do int arithmetic rather than long!
+ int ivalue = (int)lvalue;
+ c = ivalue%10;
+ ivalue /= 10;
+ while ( c == 0 ){
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ while ( ivalue != 0){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ } else {
+ // same algorithm as above (same bugs, too )
+ // but using long arithmetic.
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ while ( c == 0 ){
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ }
+ while ( lvalue != 0L ){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ }
+ this.decExponent = decExponent+1;
+ this.firstDigitIndex = digitno;
+ this.nDigits = this.digits.length - digitno;
+ }
+
+ private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+ {
+ assert fractBits > 0 ; // fractBits here can't be zero or negative
+ assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+ // number of significant bits of fractBits;
+ final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+ // reset flags to default values as dtoa() does not always set these
+ // flags and a prior call to dtoa() might have set them to incorrect
+ // values with respect to the current state.
+ decimalDigitsRoundedUp = false;
+ exactDecimalConversion = false;
+
+ // number of significant bits to the right of the point.
+ int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+ //
+ // We can do this:
+ // take the fraction bits, which are normalized.
+ // (a) nTinyBits == 0: Shift left or right appropriately
+ // to align the binary point at the extreme right, i.e.
+ // where a long int point is expected to be. The integer
+ // result is easily converted to a string.
+ // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+ // which effectively converts to long and scales by
+ // 2^nTinyBits. Then multiply by 5^nTinyBits to
+ // complete the scaling. We know this won't overflow
+ // because we just counted the number of bits necessary
+ // in the result. The integer you get from this can
+ // then be converted to a string pretty easily.
+ //
+ if ( nTinyBits == 0 ) {
+ int insignificant;
+ if ( binExp > nSignificantBits ){
+ insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+ } else {
+ insignificant = 0;
+ }
+ if ( binExp >= EXP_SHIFT ){
+ fractBits <<= (binExp-EXP_SHIFT);
+ } else {
+ fractBits >>>= (EXP_SHIFT-binExp) ;
+ }
+ developLongDigits( 0, fractBits, insignificant );
+ return;
+ }
+ //
+ // The following causes excess digits to be printed
+ // out in the single-float case. Our manipulation of
+ // halfULP here is apparently not correct. If we
+ // better understand how this works, perhaps we can
+ // use this special case again. But for the time being,
+ // we do not.
+ // else {
+ // fractBits >>>= EXP_SHIFT+1-nFractBits;
+ // fractBits//= long5pow[ nTinyBits ];
+ // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+ // return;
+ // }
+ //
+ }
+ }
+ //
+ // This is the hard case. We are going to compute large positive
+ // integers B and S and integer decExp, s.t.
+ // d = ( B / S )// 10^decExp
+ // 1 <= B / S < 10
+ // Obvious choices are:
+ // decExp = floor( log10(d) )
+ // B = d// 2^nTinyBits// 10^max( 0, -decExp )
+ // S = 10^max( 0, decExp)// 2^nTinyBits
+ // (noting that nTinyBits has already been forced to non-negative)
+ // I am also going to compute a large positive integer
+ // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+ // i.e. M is (1/2) of the ULP of d, scaled like B.
+ // When we iterate through dividing B/S and picking off the
+ // quotient bits, we will know when to stop when the remainder
+ // is <= M.
+ //
+ // We keep track of powers of 2 and powers of 5.
+ //
+ int decExp = estimateDecExp(fractBits,binExp);
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ //
+ // the long integer fractBits contains the (nFractBits) interesting
+ // bits from the mantissa of d ( hidden 1 added if necessary) followed
+ // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+ // I will shift out those zeros before turning fractBits into a
+ // FDBigInteger. The resulting whole number will be
+ // d * 2^(nFractBits-1-binExp).
+ //
+ fractBits >>>= tailZeros;
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ //
+ // HACK!! For exact powers of two, the next smallest number
+ // is only half as far away as we think (because the meaning of
+ // ULP changes at power-of-two bounds) for this reason, we
+ // hack M2. Hope this works.
+ //
+ if ( nFractBits == 1 ) {
+ M2 -= 1;
+ }
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ //
+ // Construct, Scale, iterate.
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ //
+ // Detect the special cases where all the numbers we are about
+ // to compute will fit in int or long integers.
+ // In these cases, we will avoid doing FDBigInteger arithmetic.
+ // We use the same algorithms, except that we "normalize"
+ // our FDBigIntegers before iterating. This is to make division easier,
+ // as it makes our fist guess (quotient of high-order words)
+ // more accurate!
+ //
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ // binary digits needed to represent B, approx.
+ int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+ // binary digits needed to represent 10*S, approx.
+ int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+ int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+ int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+ int tens = s * 10;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+ long s = FDBigInteger.LONG_5_POW[S5] << S2;
+ long m = FDBigInteger.LONG_5_POW[M5] << M2;
+ long tens = s * 10L;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ }
+ } else {
+ //
+ // We really must do FDBigInteger arithmetic.
+ // Fist, construct our FDBigInteger initial values.
+ //
+ FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+ int shiftBias = Sval.getNormalizationBias();
+ Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+ FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+ FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+ FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ assert q < 10 : q; // excessively large digit
+ Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval = Bval.leftShift(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else {
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+ }
+ this.decExponent = decExp+1;
+ this.firstDigitIndex = 0;
+ this.nDigits = ndigit;
+ //
+ // Last digit gets rounded based on stopping condition.
+ //
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+ roundup();
+ }
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ // add one to the least significant digit.
+ // in the unlikely event there is a carry out, deal with it.
+ // assert that this will only happen where there
+ // is only one digit, e.g. (float)1e-44 seems to do it.
+ //
+ private void roundup() {
+ int i = (firstDigitIndex + nDigits - 1);
+ int q = digits[i];
+ if (q == '9') {
+ while (q == '9' && i > firstDigitIndex) {
+ digits[i] = '0';
+ q = digits[--i];
+ }
+ if (q == '9') {
+ // carryout! High-order 1, rest 0s, larger exp.
+ decExponent += 1;
+ digits[firstDigitIndex] = '1';
+ return;
+ }
+ // else fall through.
+ }
+ digits[i] = (char) (q + 1);
+ decimalDigitsRoundedUp = true;
+ }
+
+ /**
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ */
+ static int estimateDecExp(long fractBits, int binExp) {
+ double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+ double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+ long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw
+ int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+ boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ if(exponent>=0 && exponent<52) { // hot path
+ long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+ int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+ return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+ } else if (exponent < 0) {
+ return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+ ( (isNegative) ? -1 : 0) );
+ } else { //if (exponent >= 52)
+ return (int)d;
+ }
+ }
+
+ private static int insignificantDigits(int insignificant) {
+ int i;
+ for ( i = 0; insignificant >= 10L; i++ ) {
+ insignificant /= 10L;
+ }
+ return i;
+ }
+
+ /**
+ * Calculates
+ * <pre>
+ * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+ * </pre>
+ */
+ private static int insignificantDigitsForPow2(int p2) {
+ if(p2>1 && p2 < insignificantDigitsNumber.length) {
+ return insignificantDigitsNumber[p2];
+ }
+ return 0;
+ }
+
+ /**
+ * If insignificant==(1L << ixd)
+ * i = insignificantDigitsNumber[idx] is the same as:
+ * int i;
+ * for ( i = 0; insignificant >= 10L; i++ )
+ * insignificant /= 10L;
+ */
+ private static int[] insignificantDigitsNumber = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+ 12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+ 15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 19
+ };
+
+ // approximately ceil( log2( long5pow[i] ) )
+ private static final int[] N_5_BITS = {
+ 0,
+ 3,
+ 5,
+ 7,
+ 10,
+ 12,
+ 14,
+ 17,
+ 19,
+ 21,
+ 24,
+ 26,
+ 28,
+ 31,
+ 33,
+ 35,
+ 38,
+ 40,
+ 42,
+ 45,
+ 47,
+ 49,
+ 52,
+ 54,
+ 56,
+ 59,
+ 61,
+ };
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) {
+ result[0] = '-';
+ i = 1;
+ }
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent - charLength;
+ Arrays.fill(result,i,i+charLength,'0');
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <= 0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ Arrays.fill(result, i, i-decExponent, '0');
+ i -= decExponent;
+ }
+ System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[firstDigitIndex];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+ i += nDigits - 1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent + 1;
+ } else {
+ e = decExponent - 1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char) (e + '0');
+ } else if (e <= 99) {
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ } else {
+ result[i++] = (char) (e / 100 + '0');
+ e %= 100;
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ }
+ }
+ return i;
+ }
+
+ }
+
+ private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+ new ThreadLocal<BinaryToASCIIBuffer>() {
+ @Override
+ protected BinaryToASCIIBuffer initialValue() {
+ return new BinaryToASCIIBuffer();
+ }
+ };
+
+ private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+ return threadLocalBinaryToASCIIBuffer.get();
+ }
+
+ /**
+ * A converter which can process an ASCII <code>String</code> representation
+ * of a single or double precision floating point value into a
+ * <code>float</code> or a <code>double</code>.
+ */
+ interface ASCIIToBinaryConverter {
+
+ double doubleValue();
+
+ float floatValue();
+
+ }
+
+ /**
+ * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+ */
+ static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ final private double doubleVal;
+ final private float floatVal;
+
+ public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+ this.doubleVal = doubleVal;
+ this.floatVal = floatVal;
+ }
+
+ @Override
+ public double doubleValue() {
+ return doubleVal;
+ }
+
+ @Override
+ public float floatValue() {
+ return floatVal;
+ }
+ }
+
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+ /**
+ * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+ */
+ static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+
+ ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+ {
+ this.isNegative = negSign;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+ @Override
+ public double doubleValue() {
+ int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to a long integer.
+ //
+ // (special performance hack: start to do it using int)
+ int iValue = (int) digits[0] - (int) '0';
+ int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+ for (int i = 1; i < iDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ long lValue = (long) iValue;
+ for (int i = iDigits; i < kDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ int exp = decExponent - kDigits;
+ //
+ // lValue now contains a long integer with the value of
+ // the first kDigits digits of the number.
+ // dValue contains the (double) of the same.
+ //
+
+ if (nDigits <= MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here
+ //
+ if (exp == 0 || dValue == 0.0) {
+ return (isNegative) ? -dValue : dValue; // small floating integer
+ }
+ else if (exp >= 0) {
+ if (exp <= MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ double rValue = dValue * SMALL_10_POW[exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ int slop = MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply dValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ dValue *= SMALL_10_POW[slop];
+ double rValue = dValue * SMALL_10_POW[exp - slop];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ double rValue = dValue / SMALL_10_POW[-exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ }
+
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ //
+ if (exp > 0) {
+ if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could overflow.
+ //
+ double t = dValue * BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ //
+ // It did overflow.
+ // Look more closely at the result.
+ // If the exponent is just one too large,
+ // then use the maximum finite as our estimate
+ // value. Else call the result infinity
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two larger than
+ // Double.MAX_VALUE ).
+ //
+ t = dValue / 2.0;
+ t *= BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could underflow.
+ //
+ double t = dValue * TINY_10_POW[j];
+ if (t == 0.0) {
+ //
+ // It did underflow.
+ // Look more closely at the result.
+ // If the exponent is just one too small,
+ // then use the minimum finite as our estimate
+ // value. Else call the result 0.0
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two less than
+ // Double.MIN_VALUE ).
+ //
+ t = dValue * 2.0;
+ t *= TINY_10_POW[j];
+ if (t == 0.0) {
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ //
+ // dValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > MAX_NDIGITS) {
+ nDigits = MAX_NDIGITS + 1;
+ digits[MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+ long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+ int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (63 - EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= DoubleConsts.EXP_BIAS;
+ int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -DoubleConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+ }
+ return Double.longBitsToDouble(ieeeBits);
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a float.
+ * This is distinct from doubleValue() to avoid the extremely
+ * unlikely case of a double rounding error, wherein the conversion
+ * to double has one rounding error, and the conversion of that double
+ * to a float has another rounding error, IN THE WRONG DIRECTION,
+ * ( because of the preference to a zero low-order bit ).
+ */
+ @Override
+ public float floatValue() {
+ int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to an integer.
+ //
+ int iValue = (int) digits[0] - (int) '0';
+ for (int i = 1; i < kDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ float fValue = (float) iValue;
+ int exp = decExponent - kDigits;
+ //
+ // iValue now contains an integer with the value of
+ // the first kDigits digits of the number.
+ // fValue contains the (float) of the same.
+ //
+
+ if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here.
+ //
+ if (exp == 0 || fValue == 0.0f) {
+ return (isNegative) ? -fValue : fValue; // small floating integer
+ } else if (exp >= 0) {
+ if (exp <= SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ fValue *= SINGLE_SMALL_10_POW[exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply fValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ fValue *= SINGLE_SMALL_10_POW[slop];
+ fValue *= SINGLE_SMALL_10_POW[exp - slop];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ fValue /= SINGLE_SMALL_10_POW[-exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+ //
+ // In double-precision, this is an exact floating integer.
+ // So we can compute to double, then shorten to float
+ // with one round, and get the right answer.
+ //
+ // First, finish accumulating digits.
+ // Then convert that integer to a double, multiply
+ // by the appropriate power of ten, and convert to float.
+ //
+ long lValue = (long) iValue;
+ for (int i = kDigits; i < nDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ exp = decExponent - nDigits;
+ dValue *= SMALL_10_POW[exp];
+ fValue = (float) dValue;
+ return (isNegative) ? -fValue : fValue;
+
+ }
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ // Scaling uses doubles to avoid overflow/underflow.
+ //
+ double dValue = fValue;
+ if (exp > 0) {
+ if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0f : 0.0f;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ }
+ }
+ fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+ //
+ // fValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > SINGLE_MAX_NDIGITS) {
+ nDigits = SINGLE_MAX_NDIGITS + 1;
+ digits[SINGLE_MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+ int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= SINGLE_FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+ int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= FloatConsts.EXP_BIAS;
+ int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -FloatConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+ }
+ return Float.intBitsToFloat(ieeeBits);
+ }
+
+
+ /**
+ * All the positive powers of 10 that can be
+ * represented exactly in double/float.
+ */
+ private static final double[] SMALL_10_POW = {
+ 1.0e0,
+ 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+ 1.0e21, 1.0e22
+ };
+
+ private static final float[] SINGLE_SMALL_10_POW = {
+ 1.0e0f,
+ 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+ 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+ };
+
+ private static final double[] BIG_10_POW = {
+ 1e16, 1e32, 1e64, 1e128, 1e256 };
+ private static final double[] TINY_10_POW = {
+ 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+ private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+ private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @return The converter.
+ */
+ public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+ return getBinaryToASCIIConverter(d, true);
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @param isCompatibleFormat
+ * @return The converter.
+ */
+ static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+ long dBits = Double.doubleToRawLongBits(d);
+ boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+ int binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(63-EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 64-leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= FRACT_HOB;
+ nSignificantBits = EXP_SHIFT+1;
+ }
+ binExp -= DoubleConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+ return buf;
+ }
+
+ private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+ int fBits = Float.floatToRawIntBits( f );
+ boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+ int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+ int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= SINGLE_FRACT_HOB;
+ nSignificantBits = SINGLE_EXP_SHIFT+1;
+ }
+ binExp -= FloatConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+ return buf;
+ }
+
+ @SuppressWarnings("fallthrough")
+ static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int len = in.length();
+ if ( len == 0 ) {
+ throw new NumberFormatException("empty String");
+ }
+ int i = 0;
+ switch (in.charAt(i)){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+ c = in.charAt(i);
+ if(c == 'N') { // Check for NaN
+ if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+ return A2BC_NOT_A_NUMBER;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if(c == 'I') { // Check for Infinity strings
+ if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+ return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (len > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) { // possible hex string
+ return parseHexString(in);
+ }
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ len ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+
+ skipLeadingZerosLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c == '0') {
+ nLeadZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break skipLeadingZerosLoop;
+ }
+ i++;
+ }
+ digitLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c >= '1' && c <= '9') {
+ digits[nDigits++] = c;
+ nTrailZero = 0;
+ } else if (c == '0') {
+ digits[nDigits++] = c;
+ nTrailZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break digitLoop;
+ }
+ i++;
+ }
+ nDigits -=nTrailZero;
+ //
+ // At this point, we've scanned all the digits and decimal
+ // point we're going to see. Trim off leading and trailing
+ // zeros, which will just confuse us later, and adjust
+ // our initial decimal exponent accordingly.
+ // To review:
+ // we have seen i total characters.
+ // nLeadZero of them were zeros before any other digits.
+ // nTrailZero of them were zeros after any other digits.
+ // if ( decSeen ), then a . was seen after decPt characters
+ // ( including leading zeros which have been discarded )
+ // nDigits characters were neither lead nor trailing
+ // zeros, nor point
+ //
+ //
+ // special hack: if we saw no non-zero digits, then the
+ // answer is zero!
+ // Unfortunately, we feel honor-bound to keep parsing!
+ //
+ boolean isZero = (nDigits == 0);
+ if ( isZero && nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+ //
+ // Our initial exponent is decPt, adjusted by the number of
+ // discarded zeros. Or, if there was no decPt,
+ // then its just nDigits adjusted by discarded trailing zeros.
+ //
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits + nTrailZero;
+ }
+
+ //
+ // Look for 'e' or 'E' and an optionally signed integer.
+ //
+ if ( (i < len) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < len ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ c = in.charAt(i++);
+ if(c>='0' && c<='9') {
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ } else {
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
+ if ( expOverflow || ( expVal > expLimit ) ){
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2 billion. )
+ //
+ decExp = expSign*expLimit;
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt ) {
+ break parseNumber; // certainly bad
+ }
+ }
+ //
+ // We parsed everything we could.
+ // If there are leftovers, then this is not good input!
+ //
+ if ( i < len &&
+ ((i != len - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+ if(isZero) {
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ private static class HexFloatPattern {
+ /**
+ * Grammar is compatible with hexadecimal floating-point constants
+ * described in section 6.4.4.2 of the C99 specification.
+ */
+ private static final Pattern VALUE = Pattern.compile(
+ //1 234 56 7 8 9
+ "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+ );
+ }
+
+ /**
+ * Converts string s to a suitable floating decimal; uses the
+ * double constructor and sets the roundDir variable appropriately
+ * in case the value is later converted to a float.
+ *
+ * @param s The <code>String</code> to parse.
+ */
+ static ASCIIToBinaryConverter parseHexString(String s) {
+ // Verify string is a member of the hexadecimal floating-point
+ // string language.
+ Matcher m = HexFloatPattern.VALUE.matcher(s);
+ boolean validInput = m.matches();
+ if (!validInput) {
+ // Input does not match pattern
+ throw new NumberFormatException("For input string: \"" + s + "\"");
+ } else { // validInput
+ //
+ // We must isolate the sign, significand, and exponent
+ // fields. The sign value is straightforward. Since
+ // floating-point numbers are stored with a normalized
+ // representation, the significand and exponent are
+ // interrelated.
+ //
+ // After extracting the sign, we normalized the
+ // significand as a hexadecimal value, calculating an
+ // exponent adjust for any shifts made during
+ // normalization. If the significand is zero, the
+ // exponent doesn't need to be examined since the output
+ // will be zero.
+ //
+ // Next the exponent in the input string is extracted.
+ // Afterwards, the significand is normalized as a *binary*
+ // value and the input value's normalized exponent can be
+ // computed. The significand bits are copied into a
+ // double significand; if the string has more logical bits
+ // than can fit in a double, the extra bits affect the
+ // round and sticky bits which are used to round the final
+ // value.
+ //
+ // Extract significand sign
+ String group1 = m.group(1);
+ boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+ // Extract Significand magnitude
+ //
+ // Based on the form of the significand, calculate how the
+ // binary exponent needs to be adjusted to create a
+ // normalized//hexadecimal* floating-point number; that
+ // is, a number where there is one nonzero hex digit to
+ // the left of the (hexa)decimal point. Since we are
+ // adjusting a binary, not hexadecimal exponent, the
+ // exponent is adjusted by a multiple of 4.
+ //
+ // There are a number of significand scenarios to consider;
+ // letters are used in indicate nonzero digits:
+ //
+ // 1. 000xxxx => x.xxx normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 2. 000xxx.yyyy => x.xxyyyy normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 3. .000yyy => y.yy normalized
+ // decrease exponent by (number of zeros + 1)*4
+ //
+ // 4. 000.00000yyy => y.yy normalized
+ // decrease exponent by (number of zeros to right of point + 1)*4
+ //
+ // If the significand is exactly zero, return a properly
+ // signed zero.
+ //
+
+ String significandString = null;
+ int signifLength = 0;
+ int exponentAdjust = 0;
+ {
+ int leftDigits = 0; // number of meaningful digits to
+ // left of "decimal" point
+ // (leading zeros stripped)
+ int rightDigits = 0; // number of digits to right of
+ // "decimal" point; leading zeros
+ // must always be accounted for
+ //
+ // The significand is made up of either
+ //
+ // 1. group 4 entirely (integer portion only)
+ //
+ // OR
+ //
+ // 2. the fractional portion from group 7 plus any
+ // (optional) integer portions from group 6.
+ //
+ String group4;
+ if ((group4 = m.group(4)) != null) { // Integer-only significand
+ // Leading zeros never matter on the integer portion
+ significandString = stripLeadingZeros(group4);
+ leftDigits = significandString.length();
+ } else {
+ // Group 6 is the optional integer; leading zeros
+ // never matter on the integer portion
+ String group6 = stripLeadingZeros(m.group(6));
+ leftDigits = group6.length();
+
+ // fraction
+ String group7 = m.group(7);
+ rightDigits = group7.length();
+
+ // Turn "integer.fraction" into "integer"+"fraction"
+ significandString =
+ ((group6 == null) ? "" : group6) + // is the null
+ // check necessary?
+ group7;
+ }
+
+ significandString = stripLeadingZeros(significandString);
+ signifLength = significandString.length();
+
+ //
+ // Adjust exponent as described above
+ //
+ if (leftDigits >= 1) { // Cases 1 and 2
+ exponentAdjust = 4 * (leftDigits - 1);
+ } else { // Cases 3 and 4
+ exponentAdjust = -4 * (rightDigits - signifLength + 1);
+ }
+
+ // If the significand is zero, the exponent doesn't
+ // matter; return a properly signed zero.
+
+ if (signifLength == 0) { // Only zeros in input
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ }
+
+ // Extract Exponent
+ //
+ // Use an int to read in the exponent value; this should
+ // provide more than sufficient range for non-contrived
+ // inputs. If reading the exponent in as an int does
+ // overflow, examine the sign of the exponent and
+ // significand to determine what to do.
+ //
+ String group8 = m.group(8);
+ boolean positiveExponent = (group8 == null) || group8.equals("+");
+ long unsignedRawExponent;
+ try {
+ unsignedRawExponent = Integer.parseInt(m.group(9));
+ }
+ catch (NumberFormatException e) {
+ // At this point, we know the exponent is
+ // syntactically well-formed as a sequence of
+ // digits. Therefore, if an NumberFormatException
+ // is thrown, it must be due to overflowing int's
+ // range. Also, at this point, we have already
+ // checked for a zero significand. Thus the signs
+ // of the exponent and significand determine the
+ // final result:
+ //
+ // significand
+ // + -
+ // exponent + +infinity -infinity
+ // - +0.0 -0.0
+ return isNegative ?
+ (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+ : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+ }
+
+ long rawExponent =
+ (positiveExponent ? 1L : -1L) * // exponent sign
+ unsignedRawExponent; // exponent magnitude
+
+ // Calculate partially adjusted exponent
+ long exponent = rawExponent + exponentAdjust;
+
+ // Starting copying non-zero bits into proper position in
+ // a long; copy explicit bit too; this will be masked
+ // later for normal values.
+
+ boolean round = false;
+ boolean sticky = false;
+ int nextShift = 0;
+ long significand = 0L;
+ // First iteration is different, since we only copy
+ // from the leading significand bit; one more exponent
+ // adjust will be needed...
+
+ // IMPORTANT: make leadingDigit a long to avoid
+ // surprising shift semantics!
+ long leadingDigit = getHexDigit(significandString, 0);
+
+ //
+ // Left shift the leading digit (53 - (bit position of
+ // leading 1 in digit)); this sets the top bit of the
+ // significand to 1. The nextShift value is adjusted
+ // to take into account the number of bit positions of
+ // the leadingDigit actually used. Finally, the
+ // exponent is adjusted to normalize the significand
+ // as a binary value, not just a hex value.
+ //
+ if (leadingDigit == 1) {
+ significand |= leadingDigit << 52;
+ nextShift = 52 - 4;
+ // exponent += 0
+ } else if (leadingDigit <= 3) { // [2, 3]
+ significand |= leadingDigit << 51;
+ nextShift = 52 - 5;
+ exponent += 1;
+ } else if (leadingDigit <= 7) { // [4, 7]
+ significand |= leadingDigit << 50;
+ nextShift = 52 - 6;
+ exponent += 2;
+ } else if (leadingDigit <= 15) { // [8, f]
+ significand |= leadingDigit << 49;
+ nextShift = 52 - 7;
+ exponent += 3;
+ } else {
+ throw new AssertionError("Result from digit conversion too large!");
+ }
+ // The preceding if-else could be replaced by a single
+ // code block based on the high-order bit set in
+ // leadingDigit. Given leadingOnePosition,
+
+ // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+ // nextShift = 52 - (3 + leadingOnePosition);
+ // exponent += (leadingOnePosition-1);
+
+ //
+ // Now the exponent variable is equal to the normalized
+ // binary exponent. Code below will make representation
+ // adjustments if the exponent is incremented after
+ // rounding (includes overflows to infinity) or if the
+ // result is subnormal.
+ //
+
+ // Copy digit into significand until the significand can't
+ // hold another full hex digit or there are no more input
+ // hex digits.
+ int i = 0;
+ for (i = 1;
+ i < signifLength && nextShift >= 0;
+ i++) {
+ long currentDigit = getHexDigit(significandString, i);
+ significand |= (currentDigit << nextShift);
+ nextShift -= 4;
+ }
+
+ // After the above loop, the bulk of the string is copied.
+ // Now, we must copy any partial hex digits into the
+ // significand AND compute the round bit and start computing
+ // sticky bit.
+
+ if (i < signifLength) { // at least one hex input digit exists
+ long currentDigit = getHexDigit(significandString, i);
+
+ // from nextShift, figure out how many bits need
+ // to be copied, if any
+ switch (nextShift) { // must be negative
+ case -1:
+ // three bits need to be copied in; can
+ // set round bit
+ significand |= ((currentDigit & 0xEL) >> 1);
+ round = (currentDigit & 0x1L) != 0L;
+ break;
+
+ case -2:
+ // two bits need to be copied in; can
+ // set round and start sticky
+ significand |= ((currentDigit & 0xCL) >> 2);
+ round = (currentDigit & 0x2L) != 0L;
+ sticky = (currentDigit & 0x1L) != 0;
+ break;
+
+ case -3:
+ // one bit needs to be copied in
+ significand |= ((currentDigit & 0x8L) >> 3);
+ // Now set round and start sticky, if possible
+ round = (currentDigit & 0x4L) != 0L;
+ sticky = (currentDigit & 0x3L) != 0;
+ break;
+
+ case -4:
+ // all bits copied into significand; set
+ // round and start sticky
+ round = ((currentDigit & 0x8L) != 0); // is top bit set?
+ // nonzeros in three low order bits?
+ sticky = (currentDigit & 0x7L) != 0;
+ break;
+
+ default:
+ throw new AssertionError("Unexpected shift distance remainder.");
+ // break;
+ }
+
+ // Round is set; sticky might be set.
+
+ // For the sticky bit, it suffices to check the
+ // current digit and test for any nonzero digits in
+ // the remaining unprocessed input.
+ i++;
+ while (i < signifLength && !sticky) {
+ currentDigit = getHexDigit(significandString, i);
+ sticky = sticky || (currentDigit != 0);
+ i++;
+ }
+
+ }
+ // else all of string was seen, round and sticky are
+ // correct as false.
+
+ // Float calculations
+ int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+ if (exponent >= FloatConsts.MIN_EXPONENT) {
+ if (exponent > FloatConsts.MAX_EXPONENT) {
+ // Float.POSITIVE_INFINITY
+ floatBits |= FloatConsts.EXP_BIT_MASK;
+ } else {
+ int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+ }
+ } else {
+ if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+ // 0
+ } else {
+ // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+ int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+ assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+ assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= iValue >> 1;
+ }
+ }
+ float fValue = Float.intBitsToFloat(floatBits);
+
+ // Check for overflow and update exponent accordingly.
+ if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
+ // overflow to properly signed infinity
+ return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ } else { // Finite return value
+ if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+ exponent >= DoubleConsts.MIN_EXPONENT) {
+
+ // The result returned in this block cannot be a
+ // zero or subnormal; however after the
+ // significand is adjusted from rounding, we could
+ // still overflow in infinity.
+
+ // AND exponent bits into significand; if the
+ // significand is incremented and overflows from
+ // rounding, this combination will update the
+ // exponent correctly, even in the case of
+ // Double.MAX_VALUE overflowing to infinity.
+
+ significand = ((( exponent +
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+ } else { // Subnormal or zero
+ // (exponent < DoubleConsts.MIN_EXPONENT)
+
+ if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+ // No way to round back to nonzero value
+ // regardless of significand if the exponent is
+ // less than -1075.
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+ //
+ // Find bit position to round to; recompute
+ // round and sticky bits, and shift
+ // significand right appropriately.
+ //
+
+ sticky = sticky || round;
+ round = false;
+
+ // Number of bits of significand to preserve is
+ // exponent - abs_min_exp +1
+ // check:
+ // -1075 +1074 + 1 = 0
+ // -1023 +1074 + 1 = 52
+
+ int bitsDiscarded = 53 -
+ ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+ assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+ // What to do here:
+ // First, isolate the new round bit
+ round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+ if (bitsDiscarded > 1) {
+ // create mask to update sticky bits; low
+ // order bitsDiscarded bits should be 1
+ long mask = ~((~0L) << (bitsDiscarded - 1));
+ sticky = sticky || ((significand & mask) != 0L);
+ }
+
+ // Now, discard the bits
+ significand = significand >> bitsDiscarded;
+
+ significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+ }
+ }
+
+ // The significand variable now contains the currently
+ // appropriate exponent bits too.
+
+ //
+ // Determine if significand should be incremented;
+ // making this determination depends on the least
+ // significant bit and the round and sticky bits.
+ //
+ // Round to nearest even rounding table, adapted from
+ // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+ // The digit to the left of the "decimal" point is the
+ // least significant bit, the digits to the right of
+ // the point are the round and sticky bits
+ //
+ // Number Round(x)
+ // x0.00 x0.
+ // x0.01 x0.
+ // x0.10 x0.
+ // x0.11 x1. = x0. +1
+ // x1.00 x1.
+ // x1.01 x1.
+ // x1.10 x1. + 1
+ // x1.11 x1. + 1
+ //
+ boolean leastZero = ((significand & 1L) == 0L);
+ if ((leastZero && round && sticky) ||
+ ((!leastZero) && round)) {
+ significand++;
+ }
+
+ double value = isNegative ?
+ Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+ Double.longBitsToDouble(significand );
+
+ return new PreparedASCIIToBinaryBuffer(value, fValue);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>s</code> with any leading zeros removed.
+ */
+ static String stripLeadingZeros(String s) {
+// return s.replaceFirst("^0+", "");
+ if(!s.isEmpty() && s.charAt(0)=='0') {
+ for(int i=1; i<s.length(); i++) {
+ if(s.charAt(i)!='0') {
+ return s.substring(i);
+ }
+ }
+ return "";
+ }
+ return s;
+ }
+
+ /**
+ * Extracts a hexadecimal digit from position <code>position</code>
+ * of string <code>s</code>.
+ */
+ static int getHexDigit(String s, int position) {
+ int value = Character.digit(s.charAt(position), 16);
+ if (value <= -1 || value >= 16) {
+ throw new AssertionError("Unexpected failure of digit conversion of " +
+ s.charAt(position));
+ }
+ return value;
+ }
+}
diff --git a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java b/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
old mode 100755
new mode 100644
index 0b6dd85..fc53920
--- a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
+++ b/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,961 +25,80 @@
package sun.misc;
-import sun.misc.FpUtils;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import java.util.regex.*;
+import java.util.Arrays;
public class FormattedFloatingDecimal{
- boolean isExceptional;
- boolean isNegative;
- int decExponent; // value set at construction, then immutable
- int decExponentRounded;
- char digits[];
- int nDigits;
- int bigIntExp;
- int bigIntNBits;
- boolean mustSetRoundDir = false;
- boolean fromHex = false;
- int roundDir = 0; // set by doubleValue
- int precision; // number of digits to the right of decimal
public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
- private Form form;
- private FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form )
- {
- isNegative = negSign;
- isExceptional = e;
- this.decExponent = decExponent;
- this.digits = digits;
- this.nDigits = n;
- this.precision = precision;
- this.form = form;
+ public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+ FloatingDecimal.BinaryToASCIIConverter fdConverter =
+ FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+ return new FormattedFloatingDecimal(precision,form, fdConverter);
}
- /*
- * Constants of the implementation
- * Most are IEEE-754 related.
- * (There are more really boring constants at the end.)
- */
- static final long signMask = 0x8000000000000000L;
- static final long expMask = 0x7ff0000000000000L;
- static final long fractMask= ~(signMask|expMask);
- static final int expShift = 52;
- static final int expBias = 1023;
- static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit
- static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
- static final int maxSmallBinExp = 62;
- static final int minSmallBinExp = -( 63 / 3 );
- static final int maxDecimalDigits = 15;
- static final int maxDecimalExponent = 308;
- static final int minDecimalExponent = -324;
- static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
+ private int decExponentRounded;
+ private char[] mantissa;
+ private char[] exponent;
- static final long highbyte = 0xff00000000000000L;
- static final long highbit = 0x8000000000000000L;
- static final long lowbytes = ~highbyte;
-
- static final int singleSignMask = 0x80000000;
- static final int singleExpMask = 0x7f800000;
- static final int singleFractMask = ~(singleSignMask|singleExpMask);
- static final int singleExpShift = 23;
- static final int singleFractHOB = 1<<singleExpShift;
- static final int singleExpBias = 127;
- static final int singleMaxDecimalDigits = 7;
- static final int singleMaxDecimalExponent = 38;
- static final int singleMinDecimalExponent = -45;
-
- static final int intDecimalDigits = 9;
-
-
- /*
- * count number of bits from high-order 1 bit to low-order 1 bit,
- * inclusive.
- */
- private static int
- countBits( long v ){
- //
- // the strategy is to shift until we get a non-zero sign bit
- // then shift until we have no bits left, counting the difference.
- // we do byte shifting as a hack. Hope it helps.
- //
- if ( v == 0L ) return 0;
-
- while ( ( v & highbyte ) == 0L ){
- v <<= 8;
- }
- while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
- v <<= 1;
- }
-
- int n = 0;
- while (( v & lowbytes ) != 0L ){
- v <<= 8;
- n += 8;
- }
- while ( v != 0L ){
- v <<= 1;
- n += 1;
- }
- return n;
- }
-
- /*
- * Keep big powers of 5 handy for future reference.
- */
- private static FDBigInt b5p[];
-
- private static synchronized FDBigInt
- big5pow( int p ){
- assert p >= 0 : p; // negative power of 5
- if ( b5p == null ){
- b5p = new FDBigInt[ p+1 ];
- }else if (b5p.length <= p ){
- FDBigInt t[] = new FDBigInt[ p+1 ];
- System.arraycopy( b5p, 0, t, 0, b5p.length );
- b5p = t;
- }
- if ( b5p[p] != null )
- return b5p[p];
- else if ( p < small5pow.length )
- return b5p[p] = new FDBigInt( small5pow[p] );
- else if ( p < long5pow.length )
- return b5p[p] = new FDBigInt( long5pow[p] );
- else {
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- FDBigInt bigq = b5p[q];
- if ( bigq == null )
- bigq = big5pow ( q );
- if ( r < small5pow.length ){
- return (b5p[p] = bigq.mult( small5pow[r] ) );
- }else{
- FDBigInt bigr = b5p[ r ];
- if ( bigr == null )
- bigr = big5pow( r );
- return (b5p[p] = bigq.mult( bigr ) );
- }
- }
- }
-
- //
- // a common operation
- //
- private static FDBigInt
- multPow52( FDBigInt v, int p5, int p2 ){
- if ( p5 != 0 ){
- if ( p5 < small5pow.length ){
- v = v.mult( small5pow[p5] );
- } else {
- v = v.mult( big5pow( p5 ) );
- }
- }
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- //
- // another common operation
- //
- private static FDBigInt
- constructPow52( int p5, int p2 ){
- FDBigInt v = new FDBigInt( big5pow( p5 ) );
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- /*
- * Make a floating double into a FDBigInt.
- * This could also be structured as a FDBigInt
- * constructor, but we'd have to build a lot of knowledge
- * about floating-point representation into it, and we don't want to.
- *
- * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- *
- */
- private FDBigInt
- doubleToBigInt( double dval ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- lbits &= fractMask;
- if ( binexp > 0 ){
- lbits |= fractHOB;
- } else {
- assert lbits != 0L : lbits; // doubleToBigInt(0.0)
- binexp +=1;
- while ( (lbits & fractHOB ) == 0L){
- lbits <<= 1;
- binexp -= 1;
- }
- }
- binexp -= expBias;
- int nbits = countBits( lbits );
- /*
- * We now know where the high-order 1 bit is,
- * and we know how many there are.
- */
- int lowOrderZeros = expShift+1-nbits;
- lbits >>>= lowOrderZeros;
-
- bigIntExp = binexp+1-nbits;
- bigIntNBits = nbits;
- return new FDBigInt( lbits );
- }
-
- /*
- * Compute a number that is the ULP of the given value,
- * for purposes of addition/subtraction. Generally easy.
- * More difficult if subtracting and the argument
- * is a normalized a power of 2, as the ULP changes at these points.
- */
- private static double ulp( double dval, boolean subtracting ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- double ulpval;
- if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
- // for subtraction from normalized, powers of 2,
- // use next-smaller exponent
- binexp -= 1;
- }
- if ( binexp > expShift ){
- ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
- } else if ( binexp == 0 ){
- ulpval = Double.MIN_VALUE;
- } else {
- ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
- }
- if ( subtracting ) ulpval = - ulpval;
-
- return ulpval;
- }
-
- /*
- * Round a double to a float.
- * In addition to the fraction bits of the double,
- * look at the class instance variable roundDir,
- * which should help us avoid double-rounding error.
- * roundDir was set in hardValueOf if the estimate was
- * close enough, but not exact. It tells us which direction
- * of rounding is preferred.
- */
- float
- stickyRound( double dval ){
- long lbits = Double.doubleToLongBits( dval );
- long binexp = lbits & expMask;
- if ( binexp == 0L || binexp == expMask ){
- // what we have here is special.
- // don't worry, the right thing will happen.
- return (float) dval;
- }
- lbits += (long)roundDir; // hack-o-matic.
- return (float)Double.longBitsToDouble( lbits );
- }
-
-
- /*
- * This is the easy subcase --
- * all the significant bits, after scaling, are held in lvalue.
- * negSign and decExponent tell us what processing and scaling
- * has already been done. Exceptional cases have already been
- * stripped out.
- * In particular:
- * lvalue is a finite number (not Inf, nor NaN)
- * lvalue > 0L (not zero, nor negative).
- *
- * The only reason that we develop the digits here, rather than
- * calling on Long.toString() is that we can do it a little faster,
- * and besides want to treat trailing 0s specially. If Long.toString
- * changes, we should re-evaluate this strategy!
- */
- private void
- developLongDigits( int decExponent, long lvalue, long insignificant ){
- char digits[];
- int ndigits;
- int digitno;
- int c;
- //
- // Discard non-significant low-order bits, while rounding,
- // up to insignificant value.
- int i;
- for ( i = 0; insignificant >= 10L; i++ )
- insignificant /= 10L;
- if ( i != 0 ){
- long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
- long residue = lvalue % pow10;
- lvalue /= pow10;
- decExponent += i;
- if ( residue >= (pow10>>1) ){
- // round up based on the low-order bits we're discarding
- lvalue++;
- }
- }
- if ( lvalue <= Integer.MAX_VALUE ){
- assert lvalue > 0L : lvalue; // lvalue <= 0
- // even easier subcase!
- // can do int arithmetic rather than long!
- int ivalue = (int)lvalue;
- ndigits = 10;
- digits = (char[])(perThreadBuffer.get());
- digitno = ndigits-1;
- c = ivalue%10;
- ivalue /= 10;
- while ( c == 0 ){
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- } else {
- // same algorithm as above (same bugs, too )
- // but using long arithmetic.
- ndigits = 20;
- digits = (char[])(perThreadBuffer.get());
- digitno = ndigits-1;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- while ( c == 0 ){
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- }
- while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- }
- char result [];
- ndigits -= digitno;
- result = new char[ ndigits ];
- System.arraycopy( digits, digitno, result, 0, ndigits );
- this.digits = result;
- this.decExponent = decExponent+1;
- this.nDigits = ndigits;
- }
-
- //
- // add one to the least significant digit.
- // in the unlikely event there is a carry out,
- // deal with it.
- // assert that this will only happen where there
- // is only one digit, e.g. (float)1e-44 seems to do it.
- //
- private void
- roundup(){
- int i;
- int q = digits[ i = (nDigits-1)];
- if ( q == '9' ){
- while ( q == '9' && i > 0 ){
- digits[i] = '0';
- q = digits[--i];
- }
- if ( q == '9' ){
- // carryout! High-order 1, rest 0s, larger exp.
- decExponent += 1;
- digits[0] = '1';
- return;
- }
- // else fall through.
- }
- digits[i] = (char)(q+1);
- }
-
- // Given the desired number of digits predict the result's exponent.
- private int checkExponent(int length) {
- if (length >= nDigits || length < 0)
- return decExponent;
-
- for (int i = 0; i < length; i++)
- if (digits[i] != '9')
- // a '9' anywhere in digits will absorb the round
- return decExponent;
- return decExponent + (digits[length] >= '5' ? 1 : 0);
- }
-
- // Unlike roundup(), this method does not modify digits. It also
- // rounds at a particular precision.
- private char [] applyPrecision(int length) {
- char [] result = new char[nDigits];
- for (int i = 0; i < result.length; i++) result[i] = '0';
-
- if (length >= nDigits || length < 0) {
- // no rounding necessary
- System.arraycopy(digits, 0, result, 0, nDigits);
- return result;
- }
- if (length == 0) {
- // only one digit (0 or 1) is returned because the precision
- // excludes all significant digits
- if (digits[0] >= '5') {
- result[0] = '1';
- }
- return result;
- }
-
- int i = length;
- int q = digits[i];
- if (q >= '5' && i > 0) {
- q = digits[--i];
- if ( q == '9' ) {
- while ( q == '9' && i > 0 ){
- q = digits[--i];
+ private static final ThreadLocal<Object> threadLocalCharBuffer =
+ new ThreadLocal<Object>() {
+ @Override
+ protected Object initialValue() {
+ return new char[20];
}
- if ( q == '9' ){
- // carryout! High-order 1, rest 0s, larger exp.
- result[0] = '1';
- return result;
- }
- }
- result[i] = (char)(q + 1);
- }
- while (--i >= 0) {
- result[i] = digits[i];
- }
- return result;
+ };
+
+ private static char[] getBuffer(){
+ return (char[]) threadLocalCharBuffer.get();
}
- /*
- * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
- */
- public FormattedFloatingDecimal( double d )
- {
- this(d, Integer.MAX_VALUE, Form.COMPATIBLE);
- }
-
- public FormattedFloatingDecimal( double d, int precision, Form form )
- {
- long dBits = Double.doubleToLongBits( d );
- long fractBits;
- int binExp;
- int nSignificantBits;
-
- this.precision = precision;
- this.form = form;
-
- // discover and delete sign
- if ( (dBits&signMask) != 0 ){
- isNegative = true;
- dBits ^= signMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (dBits&expMask) >> expShift );
- fractBits = dBits&fractMask;
- if ( binExp == (int)(expMask>>expShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
+ private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+ if (fdConverter.isExceptional()) {
+ this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+ this.exponent = null;
return;
}
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&fractHOB) == 0L ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= fractHOB;
- nSignificantBits = expShift+1;
- }
- binExp -= expBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, fractBits, nSignificantBits );
- }
-
- /*
- * SECOND IMPORTANT CONSTRUCTOR: SINGLE
- */
- public FormattedFloatingDecimal( float f )
- {
- this(f, Integer.MAX_VALUE, Form.COMPATIBLE);
- }
- public FormattedFloatingDecimal( float f, int precision, Form form )
- {
- int fBits = Float.floatToIntBits( f );
- int fractBits;
- int binExp;
- int nSignificantBits;
-
- this.precision = precision;
- this.form = form;
-
- // discover and delete sign
- if ( (fBits&singleSignMask) != 0 ){
- isNegative = true;
- fBits ^= singleSignMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (fBits&singleExpMask) >> singleExpShift );
- fractBits = fBits&singleFractMask;
- if ( binExp == (int)(singleExpMask>>singleExpShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&singleFractHOB) == 0 ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= singleFractHOB;
- nSignificantBits = singleExpShift+1;
- }
- binExp -= singleExpBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
- }
-
- private void
- dtoa( int binExp, long fractBits, int nSignificantBits )
- {
- int nFractBits; // number of significant bits of fractBits;
- int nTinyBits; // number of these to the right of the point.
- int decExp;
-
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- nFractBits = countBits( fractBits );
- nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
- /*
- * We can do this:
- * take the fraction bits, which are normalized.
- * (a) nTinyBits == 0: Shift left or right appropriately
- * to align the binary point at the extreme right, i.e.
- * where a long int point is expected to be. The integer
- * result is easily converted to a string.
- * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
- * which effectively converts to long and scales by
- * 2^nTinyBits. Then multiply by 5^nTinyBits to
- * complete the scaling. We know this won't overflow
- * because we just counted the number of bits necessary
- * in the result. The integer you get from this can
- * then be converted to a string pretty easily.
- */
- long halfULP;
- if ( nTinyBits == 0 ) {
- if ( binExp > nSignificantBits ){
- halfULP = 1L << ( binExp-nSignificantBits-1);
- } else {
- halfULP = 0L;
- }
- if ( binExp >= expShift ){
- fractBits <<= (binExp-expShift);
- } else {
- fractBits >>>= (expShift-binExp) ;
- }
- developLongDigits( 0, fractBits, halfULP );
- return;
- }
- /*
- * The following causes excess digits to be printed
- * out in the single-float case. Our manipulation of
- * halfULP here is apparently not correct. If we
- * better understand how this works, perhaps we can
- * use this special case again. But for the time being,
- * we do not.
- * else {
- * fractBits >>>= expShift+1-nFractBits;
- * fractBits *= long5pow[ nTinyBits ];
- * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- * developLongDigits( -nTinyBits, fractBits, halfULP );
- * return;
- * }
- */
- }
- }
- /*
- * This is the hard case. We are going to compute large positive
- * integers B and S and integer decExp, s.t.
- * d = ( B / S ) * 10^decExp
- * 1 <= B / S < 10
- * Obvious choices are:
- * decExp = floor( log10(d) )
- * B = d * 2^nTinyBits * 10^max( 0, -decExp )
- * S = 10^max( 0, decExp) * 2^nTinyBits
- * (noting that nTinyBits has already been forced to non-negative)
- * I am also going to compute a large positive integer
- * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
- * i.e. M is (1/2) of the ULP of d, scaled like B.
- * When we iterate through dividing B/S and picking off the
- * quotient bits, we will know when to stop when the remainder
- * is <= M.
- *
- * We keep track of powers of 2 and powers of 5.
- */
-
- /*
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- * FIXME -- use more precise constants here. It costs no more.
- */
- double d2 = Double.longBitsToDouble(
- expOne | ( fractBits &~ fractHOB ) );
- decExp = (int)Math.floor(
- (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
- int Bbits; // binary digits needed to represent B, approx.
- int tenSbits; // binary digits needed to represent 10*S, approx.
- FDBigInt Sval, Bval, Mval;
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- /*
- * the long integer fractBits contains the (nFractBits) interesting
- * bits from the mantissa of d ( hidden 1 added if necessary) followed
- * by (expShift+1-nFractBits) zeros. In the interest of compactness,
- * I will shift out those zeros before turning fractBits into a
- * FDBigInt. The resulting whole number will be
- * d * 2^(nFractBits-1-binExp).
- */
- fractBits >>>= (expShift+1-nFractBits);
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- /*
- * HACK!! For exact powers of two, the next smallest number
- * is only half as far away as we think (because the meaning of
- * ULP changes at power-of-two bounds) for this reason, we
- * hack M2. Hope this works.
- */
- if ( nFractBits == 1 )
- M2 -= 1;
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- /*
- * Construct, Scale, iterate.
- * Some day, we'll write a stopping test that takes
- * account of the assymetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- char digits[] = this.digits = new char[18];
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- /*
- * Detect the special cases where all the numbers we are about
- * to compute will fit in int or long integers.
- * In these cases, we will avoid doing FDBigInt arithmetic.
- * We use the same algorithms, except that we "normalize"
- * our FDBigInts before iterating. This is to make division easier,
- * as it makes our fist guess (quotient of high-order words)
- * more accurate!
- *
- * Some day, we'll write a stopping test that takes
- * account of the assymetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
- tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * small5pow[B5] ) << B2;
- int s = small5pow[S5] << S2;
- int m = small5pow[M5] << M2;
- int tens = s * 10;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
+ char[] digits = getBuffer();
+ int nDigits = fdConverter.getDigits(digits);
+ int decExp = fdConverter.getDecimalExponent();
+ int exp;
+ boolean isNegative = fdConverter.isNegative();
+ switch (form) {
+ case COMPATIBLE:
+ exp = decExp;
+ this.decExponentRounded = exp;
+ fillCompatible(precision, digits, nDigits, exp, isNegative);
+ break;
+ case DECIMAL_FLOAT:
+ exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+ fillDecimal(precision, digits, nDigits, exp, isNegative);
+ this.decExponentRounded = exp;
+ break;
+ case SCIENTIFIC:
+ exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+ fillScientific(precision, digits, nDigits, exp, isNegative);
+ this.decExponentRounded = exp;
+ break;
+ case GENERAL:
+ exp = applyPrecision(decExp, digits, nDigits, precision);
+ // adjust precision to be the number of digits to right of decimal
+ // the real exponent to be output is actually exp - 1, not exp
+ if (exp - 1 < -4 || exp - 1 >= precision) {
+ // form = Form.SCIENTIFIC;
+ precision--;
+ fillScientific(precision, digits, nDigits, exp, isNegative);
} else {
- digits[ndigit++] = (char)('0' + q);
+ // form = Form.DECIMAL_FLOAT;
+ precision = precision - exp;
+ fillDecimal(precision, digits, nDigits, exp, isNegative);
}
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- } else {
- // still good! they're all longs!
- long b = (fractBits * long5pow[B5] ) << B2;
- long s = long5pow[S5] << S2;
- long m = long5pow[M5] << M2;
- long tens = s * 10L;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- }
- } else {
- FDBigInt tenSval;
- int shiftBias;
-
- /*
- * We really must do FDBigInt arithmetic.
- * Fist, construct our FDBigInt initial values.
- */
- Bval = multPow52( new FDBigInt( fractBits ), B5, B2 );
- Sval = constructPow52( S5, S2 );
- Mval = constructPow52( M5, M2 );
-
-
- // normalize so that division works better
- Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
- Mval.lshiftMe( shiftBias );
- tenSval = Sval.mult( 10 );
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- assert q < 10 : q; // excessively large digit
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval.lshiftMe(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else
- lowDigitDifference = 0L; // this here only for flow analysis!
+ this.decExponentRounded = exp;
+ break;
+ default:
+ assert false;
}
- this.decExponent = decExp+1;
- this.digits = digits;
- this.nDigits = ndigit;
- /*
- * Last digit gets rounded based on stopping condition.
- */
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[nDigits-1]&1) != 0 ) roundup();
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- public String
- toString(){
- // most brain-dead version
- StringBuffer result = new StringBuffer( nDigits+8 );
- if ( isNegative ){ result.append( '-' ); }
- if ( isExceptional ){
- result.append( digits, 0, nDigits );
- } else {
- result.append( "0.");
- result.append( digits, 0, nDigits );
- result.append('e');
- result.append( decExponent );
- }
- return new String(result);
- }
-
- // returns the exponent before rounding
- public int getExponent() {
- return decExponent - 1;
}
// returns the exponent after rounding has been done by applyPrecision
@@ -987,781 +106,244 @@
return decExponentRounded - 1;
}
- public int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) { result[0] = '-'; i = 1; }
- if (isExceptional) {
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- char digits [] = this.digits;
- int exp = decExponent;
- switch (form) {
- case COMPATIBLE:
- break;
- case DECIMAL_FLOAT:
- exp = checkExponent(decExponent + precision);
- digits = applyPrecision(decExponent + precision);
- break;
- case SCIENTIFIC:
- exp = checkExponent(precision + 1);
- digits = applyPrecision(precision + 1);
- break;
- case GENERAL:
- exp = checkExponent(precision);
- digits = applyPrecision(precision);
- // adjust precision to be the number of digits to right of decimal
- // the real exponent to be output is actually exp - 1, not exp
- if (exp - 1 < -4 || exp - 1 >= precision) {
- form = Form.SCIENTIFIC;
- precision--;
- } else {
- form = Form.DECIMAL_FLOAT;
- precision = precision - exp;
- }
- break;
- default:
- assert false;
- }
- decExponentRounded = exp;
+ public char[] getMantissa(){
+ return mantissa;
+ }
- if (exp > 0
- && ((form == Form.COMPATIBLE && (exp < 8))
- || (form == Form.DECIMAL_FLOAT)))
- {
- // print digits.digits.
- int charLength = Math.min(nDigits, exp);
- System.arraycopy(digits, 0, result, i, charLength);
- i += charLength;
- if (charLength < exp) {
- charLength = exp-charLength;
- for (int nz = 0; nz < charLength; nz++)
- result[i++] = '0';
- // Do not append ".0" for formatted floats since the user
- // may request that it be omitted. It is added as necessary
- // by the Formatter.
- if (form == Form.COMPATIBLE) {
- result[i++] = '.';
- result[i++] = '0';
- }
- } else {
- // Do not append ".0" for formatted floats since the user
- // may request that it be omitted. It is added as necessary
- // by the Formatter.
- if (form == Form.COMPATIBLE) {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = Math.min(nDigits - charLength, precision);
- System.arraycopy(digits, charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- } else {
- int t = Math.min(nDigits - charLength, precision);
- if (t > 0) {
- result[i++] = '.';
- System.arraycopy(digits, charLength, result, i, t);
- i += t;
- }
- }
- }
- } else if (exp <= 0
- && ((form == Form.COMPATIBLE && exp > -3)
- || (form == Form.DECIMAL_FLOAT)))
- {
- // print 0.0* digits
- result[i++] = '0';
- if (exp != 0) {
- // write '0' s before the significant digits
- int t = Math.min(-exp, precision);
- if (t > 0) {
- result[i++] = '.';
- for (int nz = 0; nz < t; nz++)
- result[i++] = '0';
- }
- }
- int t = Math.min(digits.length, precision + exp);
- if (t > 0) {
- if (i == 1)
- result[i++] = '.';
- // copy only when significant digits are within the precision
- System.arraycopy(digits, 0, result, i, t);
- i += t;
- }
+ public char[] getExponent(){
+ return exponent;
+ }
+
+ /**
+ * Returns new decExp in case of overflow.
+ */
+ private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+ if (prec >= nDigits || prec < 0) {
+ // no rounding necessary
+ return decExp;
+ }
+ if (prec == 0) {
+ // only one digit (0 or 1) is returned because the precision
+ // excludes all significant digits
+ if (digits[0] >= '5') {
+ digits[0] = '1';
+ Arrays.fill(digits, 1, nDigits, '0');
+ return decExp + 1;
} else {
- result[i++] = digits[0];
- if (form == Form.COMPATIBLE) {
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, 1, result, i, nDigits-1);
- i += nDigits-1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- } else {
- if (nDigits > 1) {
- int t = Math.min(nDigits -1, precision);
- if (t > 0) {
- result[i++] = '.';
- System.arraycopy(digits, 1, result, i, t);
- i += t;
- }
- }
- result[i++] = 'e';
- }
- int e;
- if (exp <= 0) {
- result[i++] = '-';
- e = -exp+1;
- } else {
- if (form != Form.COMPATIBLE)
- result[i++] = '+';
- e = exp-1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- if (form != Form.COMPATIBLE)
- result[i++] = '0';
- result[i++] = (char)(e+'0');
- } else if (e <= 99) {
- result[i++] = (char)(e/10 +'0');
- result[i++] = (char)(e%10 + '0');
- } else {
- result[i++] = (char)(e/100+'0');
- e %= 100;
- result[i++] = (char)(e/10+'0');
- result[i++] = (char)(e%10 + '0');
- }
+ Arrays.fill(digits, 0, nDigits, '0');
+ return decExp;
}
}
- return i;
+ int q = digits[prec];
+ if (q >= '5') {
+ int i = prec;
+ q = digits[--i];
+ if ( q == '9' ) {
+ while ( q == '9' && i > 0 ){
+ q = digits[--i];
+ }
+ if ( q == '9' ){
+ // carryout! High-order 1, rest 0s, larger exp.
+ digits[0] = '1';
+ Arrays.fill(digits, 1, nDigits, '0');
+ return decExp+1;
+ }
+ }
+ digits[i] = (char)(q + 1);
+ Arrays.fill(digits, i+1, nDigits, '0');
+ } else {
+ Arrays.fill(digits, prec, nDigits, '0');
+ }
+ return decExp;
}
- // Per-thread buffer for string/stringbuffer conversion
- private static ThreadLocal perThreadBuffer = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new char[26];
- }
- };
-
- /*
- * Take a FormattedFloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
+ /**
+ * Fills mantissa and exponent char arrays for compatible format.
*/
-
- public strictfp double doubleValue(){
- int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
- long lValue;
- double dValue;
- double rValue, tValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Double.NaN;
- else
- return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
+ private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ if (exp > 0 && exp < 8) {
+ // print digits.digits.
+ if (nDigits < exp) {
+ int extraZeros = exp - nDigits;
+ mantissa = create(isNegative, nDigits + extraZeros + 2);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+ mantissa[startIndex + nDigits + extraZeros] = '.';
+ mantissa[startIndex + nDigits + extraZeros+1] = '0';
+ } else if (exp < nDigits) {
+ int t = Math.min(nDigits - exp, precision);
+ mantissa = create(isNegative, exp + 1 + t);
+ System.arraycopy(digits, 0, mantissa, startIndex, exp);
+ mantissa[startIndex + exp ] = '.';
+ System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+ } else { // exp == digits.length
+ mantissa = create(isNegative, nDigits + 2);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ mantissa[startIndex + nDigits ] = '.';
+ mantissa[startIndex + nDigits +1] = '0';
+ }
+ } else if (exp <= 0 && exp > -3) {
+ int zeros = Math.max(0, Math.min(-exp, precision));
+ int t = Math.max(0, Math.min(nDigits, precision + exp));
+ // write '0' s before the significant digits
+ if (zeros > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex+1] = '.';
+ Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+ if (t > 0) {
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+ }
+ } else if (t > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex + 1] = '.';
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+ } else {
+ this.mantissa = create(isNegative, 1);
+ this.mantissa[startIndex] = '0';
+ }
+ } else {
+ if (nDigits > 1) {
+ mantissa = create(isNegative, nDigits + 1);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
+ } else {
+ mantissa = create(isNegative, 3);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ mantissa[startIndex + 2] = '0';
+ }
+ int e, expStartIntex;
+ boolean isNegExp = (exp <= 0);
+ if (isNegExp) {
+ e = -exp + 1;
+ expStartIntex = 1;
+ } else {
+ e = exp - 1;
+ expStartIntex = 0;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ exponent = create(isNegExp,1);
+ exponent[expStartIntex] = (char) (e + '0');
+ } else if (e <= 99) {
+ exponent = create(isNegExp,2);
+ exponent[expStartIntex] = (char) (e / 10 + '0');
+ exponent[expStartIntex+1] = (char) (e % 10 + '0');
+ } else {
+ exponent = create(isNegExp,3);
+ exponent[expStartIntex] = (char) (e / 100 + '0');
+ e %= 100;
+ exponent[expStartIntex+1] = (char) (e / 10 + '0');
+ exponent[expStartIntex+2] = (char) (e % 10 + '0');
+ }
}
- else {
- if (mustSetRoundDir) {
- roundDir = 0;
- }
- /*
- * convert the lead kDigits to a long integer.
- */
- // (special performance hack: start to do it using int)
- int iValue = (int)digits[0]-(int)'0';
- int iDigits = Math.min( kDigits, intDecimalDigits );
- for ( int i=1; i < iDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- lValue = (long)iValue;
- for ( int i=iDigits; i < kDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- dValue = (double)lValue;
- int exp = decExponent-kDigits;
- /*
- * lValue now contains a long integer with the value of
- * the first kDigits digits of the number.
- * dValue contains the (double) of the same.
- */
+ }
- if ( nDigits <= maxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here
- */
- if (exp == 0 || dValue == 0.0)
- return (isNegative)? -dValue : dValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= maxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- rValue = dValue * small10pow[exp];
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- int slop = maxDecimalDigits - kDigits;
- if ( exp <= maxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- dValue *= small10pow[slop];
- rValue = dValue * small10pow[exp-slop];
-
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp-slop];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -maxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- rValue = dValue / small10pow[-exp];
- tValue = rValue * small10pow[-exp];
- if ( mustSetRoundDir ){
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- }
-
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by approximating the right answer by,
- * naively, scaling by powers of 10.
- */
- if ( exp > 0 ){
- if ( decExponent > maxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ( (exp&15) != 0 ){
- dValue *= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= big10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could overflow.
- */
- double t = dValue * big10pow[j];
- if ( Double.isInfinite( t ) ){
- /*
- * It did overflow.
- * Look more closely at the result.
- * If the exponent is just one too large,
- * then use the maximum finite as our estimate
- * value. Else call the result infinity
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two larger than
- * Double.MAX_VALUE ).
- */
- t = dValue / 2.0;
- t *= big10pow[j];
- if ( Double.isInfinite( t ) ){
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if ( exp < 0 ){
- exp = -exp;
- if ( decExponent < minDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0 : 0.0;
- }
- if ( (exp&15) != 0 ){
- dValue /= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= tiny10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could underflow.
- */
- double t = dValue * tiny10pow[j];
- if ( t == 0.0 ){
- /*
- * It did underflow.
- * Look more closely at the result.
- * If the exponent is just one too small,
- * then use the minimum finite as our estimate
- * value. Else call the result 0.0
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two less than
- * Double.MIN_VALUE ).
- */
- t = dValue * 2.0;
- t *= tiny10pow[j];
- if ( t == 0.0 ){
- return (isNegative)? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- /*
- * dValue is now approximately the result.
- * The hard part is adjusting it, by comparison
- * with FDBigInt arithmetic.
- * Formulate the EXACT big-number result as
- * bigD0 * 10^exp
- */
- FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
- exp = decExponent - nDigits;
-
- correctionLoop:
- while(true){
- /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- */
- FDBigInt bigB = doubleToBigInt( dValue );
-
- /*
- * Scale bigD, bigB appropriately for
- * big-integer operations.
- * Naively, we multipy by powers of ten
- * and powers of two. What we actually do
- * is keep track of the powers of 5 and
- * powers of 2 we would use, then factor out
- * common divisors before doing the work.
- */
- int B2, B5; // powers of 2, 5 in bigB
- int D2, D5; // powers of 2, 5 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if ( exp >= 0 ){
- B2 = B5 = 0;
- D2 = D5 = exp;
- } else {
- B2 = B5 = -exp;
- D2 = D5 = 0;
- }
- if ( bigIntExp >= 0 ){
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if ( bigIntExp+bigIntNBits <= -expBias+1 ){
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(expBias+expShift+1)
- hulpbias = bigIntExp+ expBias + expShift;
- } else {
- hulpbias = expShift + 2 - bigIntNBits;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- bigB = multPow52( bigB, B5, B2 );
- FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInt diff;
- int cmpResult;
- boolean overvalue;
- if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
- overvalue = true; // our candidate is too big.
- diff = bigB.sub( bigD );
- if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
- // candidate is a normalized exact power of 2 and
- // is too big. We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if ( Ulp2 < 0 ){
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff.lshiftMe( 1 );
- }
- }
- } else if ( cmpResult < 0 ){
- overvalue = false; // our candidate is too small.
- diff = bigD.sub( bigB );
- } else {
- // the candidate is exactly right!
- // this happens with surprising fequency
- break correctionLoop;
- }
- FDBigInt halfUlp = constructPow52( B5, Ulp2 );
- if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
- // difference is small.
- // this is close enough
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else if ( cmpResult == 0 ){
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- dValue += 0.5*ulp( dValue, overvalue );
- // should check for bigIntNBits == 1 here??
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- dValue += ulp( dValue, overvalue );
- if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
- break correctionLoop; // oops. Fell off end of range.
- continue; // try again.
- }
-
- }
- return (isNegative)? -dValue : dValue;
+ private static char[] create(boolean isNegative, int size) {
+ if(isNegative) {
+ char[] r = new char[size +1];
+ r[0] = '-';
+ return r;
+ } else {
+ return new char[size];
}
}
/*
- * Take a FormattedFloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the converstion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
+ * Fills mantissa char arrays for DECIMAL_FLOAT format.
+ * Exponent should be equal to null.
*/
-
- public strictfp float floatValue(){
- int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
- int iValue;
- float fValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Float.NaN;
- else
- return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
- }
- else {
- /*
- * convert the lead kDigits to an integer.
- */
- iValue = (int)digits[0]-(int)'0';
- for ( int i=1; i < kDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- fValue = (float)iValue;
- int exp = decExponent-kDigits;
- /*
- * iValue now contains an integer with the value of
- * the first kDigits digits of the number.
- * fValue contains the (float) of the same.
- */
-
- if ( nDigits <= singleMaxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here.
- */
- if (exp == 0 || fValue == 0.0f)
- return (isNegative)? -fValue : fValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= singleMaxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- fValue *= singleSmall10pow[exp];
- return (isNegative)? -fValue : fValue;
- }
- int slop = singleMaxDecimalDigits - kDigits;
- if ( exp <= singleMaxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- fValue *= singleSmall10pow[slop];
- fValue *= singleSmall10pow[exp-slop];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -singleMaxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- fValue /= singleSmall10pow[-exp];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
+ private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ if (exp > 0) {
+ // print digits.digits.
+ if (nDigits < exp) {
+ mantissa = create(isNegative,exp);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+ // Do not append ".0" for formatted floats since the user
+ // may request that it be omitted. It is added as necessary
+ // by the Formatter.
+ } else {
+ int t = Math.min(nDigits - exp, precision);
+ mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+ System.arraycopy(digits, 0, mantissa, startIndex, exp);
+ // Do not append ".0" for formatted floats since the user
+ // may request that it be omitted. It is added as necessary
+ // by the Formatter.
+ if (t > 0) {
+ mantissa[startIndex + exp] = '.';
+ System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
}
- } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
- /*
- * In double-precision, this is an exact floating integer.
- * So we can compute to double, then shorten to float
- * with one round, and get the right answer.
- *
- * First, finish accumulating digits.
- * Then convert that integer to a double, multiply
- * by the appropriate power of ten, and convert to float.
- */
- long lValue = (long)iValue;
- for ( int i=kDigits; i < nDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ } else if (exp <= 0) {
+ int zeros = Math.max(0, Math.min(-exp, precision));
+ int t = Math.max(0, Math.min(nDigits, precision + exp));
+ // write '0' s before the significant digits
+ if (zeros > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex+1] = '.';
+ Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+ if (t > 0) {
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
}
- double dValue = (double)lValue;
- exp = decExponent-nDigits;
- dValue *= small10pow[exp];
- fValue = (float)dValue;
- return (isNegative)? -fValue : fValue;
-
+ } else if (t > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex + 1] = '.';
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+ } else {
+ this.mantissa = create(isNegative, 1);
+ this.mantissa[startIndex] = '0';
}
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by weeding out obviously out-of-range
- * results, then convert to double and go to
- * common hard-case code.
- */
- if ( decExponent > singleMaxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- } else if ( decExponent < singleMinDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0f : 0.0f;
- }
-
- /*
- * Here, we do 'way too much work, but throwing away
- * our partial results, and going and doing the whole
- * thing as double, then throwing away half the bits that computes
- * when we convert back to float.
- *
- * The alternative is to reproduce the whole multiple-precision
- * algorythm for float precision, or to try to parameterize it
- * for common usage. The former will take about 400 lines of code,
- * and the latter I tried without success. Thus the semi-hack
- * answer here.
- */
- mustSetRoundDir = !fromHex;
- double dValue = doubleValue();
- return stickyRound( dValue );
}
}
-
- /*
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
+ /**
+ * Fills mantissa and exponent char arrays for SCIENTIFIC format.
*/
- private static final double small10pow[] = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float singleSmall10pow[] = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double big10pow[] = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double tiny10pow[] = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int maxSmallTen = small10pow.length-1;
- private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
- private static final int small5pow[] = {
- 1,
- 5,
- 5*5,
- 5*5*5,
- 5*5*5*5,
- 5*5*5*5*5,
- 5*5*5*5*5*5,
- 5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5*5
- };
-
-
- private static final long long5pow[] = {
- 1L,
- 5L,
- 5L*5,
- 5L*5*5,
- 5L*5*5*5,
- 5L*5*5*5*5,
- 5L*5*5*5*5*5,
- 5L*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int n5bits[] = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
- private static final char notANumber[] = { 'N', 'a', 'N' };
- private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
+ private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ int t = Math.max(0, Math.min(nDigits - 1, precision));
+ if (t > 0) {
+ mantissa = create(isNegative, t + 2);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+ } else {
+ mantissa = create(isNegative, 1);
+ mantissa[startIndex] = digits[0];
+ }
+ char expSign;
+ int e;
+ if (exp <= 0) {
+ expSign = '-';
+ e = -exp + 1;
+ } else {
+ expSign = '+' ;
+ e = exp - 1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ exponent = new char[] { expSign,
+ '0', (char) (e + '0') };
+ } else if (e <= 99) {
+ exponent = new char[] { expSign,
+ (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+ } else {
+ char hiExpChar = (char) (e / 100 + '0');
+ e %= 100;
+ exponent = new char[] { expSign,
+ hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+ }
+ }
}
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 9d18407..7acaa63 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1143,8 +1143,8 @@
ojluni/src/main/java/com/sun/nio/file/SensitivityWatchEventModifier.java \
ojluni/src/main/java/java/beans/ChangeListenerMap.java \
ojluni/src/main/java/java/lang/Shutdown.java \
- ojluni/src/main/java/sun/misc/FDBigInt.java \
- ojluni/src/main/java/java/lang/FloatingDecimal.java \
+ ojluni/src/main/java/sun/misc/FDBigInteger.java \
+ ojluni/src/main/java/sun/misc/FloatingDecimal.java \
ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java \
ojluni/src/main/java/java/text/spi/CollatorProvider.java \
ojluni/src/main/java/java/text/spi/DateFormatProvider.java \