Skip to content

Commit 21a7c30

Browse files
committed
Allow DD creation from an unsigned int value.
1 parent da6608d commit 21a7c30

3 files changed

Lines changed: 53 additions & 9 deletions

File tree

  • commons-numbers-core/src
    • main/java/org/apache/commons/numbers/core
    • test/java/org/apache/commons/numbers/core
  • src/changes

commons-numbers-core/src/main/java/org/apache/commons/numbers/core/DD.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ static DD of(double x, double xx) {
325325
/**
326326
* Creates the double-double number as the value {@code (x, 0)}.
327327
*
328-
* <p>Note this method exists to avoid using {@link #of(long)} for {@code integer}
328+
* <p>Note this method exists to avoid using {@link #of(long)} for {@code int}
329329
* arguments; the {@code long} variation is slower as it preserves all 64-bits
330330
* of information.
331331
*
@@ -363,13 +363,36 @@ public static DD of(long x) {
363363

364364
/**
365365
* Creates the double-double number using the argument {@code x} as an unsigned
366-
* 64-bit integer.
366+
* 32-bit integer. Equivalent to:
367367
*
368-
* <p>Note this method preserves all 64-bits of precision. It can be used to
369-
* represent the positive difference between two ordered {@code long} values
370-
* without using {@link DD#subtract(DD)}.
368+
* <pre>
369+
* DD.of((double) Integer.toUnsignedLong(x))
370+
* </pre>
371+
*
372+
* <p>Note this method exists to avoid using {@link #ofUnsigned(long)} for {@code int}
373+
* arguments as sign extension on negative values will generate an incorrect result.
374+
*
375+
* @param x Value.
376+
* @return the double-double
377+
*/
378+
public static DD ofUnsigned(int x) {
379+
return new DD(Integer.toUnsignedLong(x), 0);
380+
}
381+
382+
/**
383+
* Creates the double-double number using the argument {@code x} as an unsigned 64-bit
384+
* integer.
385+
*
386+
* <p>Zero and positive values are mapped to a numerically equal double-double value;
387+
* and negative values are mapped to a value equal to the positive {@code long} value
388+
* of the low order 63-bits plus 2<sup>63</sup>.
389+
*
390+
* <p>Note this method preserves all 64-bits of precision. It can be used to represent
391+
* the positive difference between two ordered {@code long} values without using
392+
* {@link DD#subtract(DD)}.
371393
*
372394
* <p>Given two {@code long} values {@code a <= b} the following are equivalent:
395+
*
373396
* <pre>
374397
* DD.of(b).subtract(DD.of(a))
375398
*

commons-numbers-core/src/test/java/org/apache/commons/numbers/core/DDTest.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.function.Supplier;
2828
import java.util.function.UnaryOperator;
2929
import java.util.stream.IntStream;
30-
import java.util.stream.LongStream;
3130
import java.util.stream.Stream;
3231
import org.apache.commons.rng.UniformRandomProvider;
3332
import org.apache.commons.rng.simple.RandomSource;
@@ -145,6 +144,28 @@ void testOfLong(long x) {
145144
Assertions.assertEquals(BigDecimal.valueOf(-x).subtract(bd(-x)).doubleValue(), dd.lo(), "-x lo should be remaining bits");
146145
}
147146

147+
/**
148+
* Test conversion of an unsigned {@code int}.
149+
*/
150+
@ParameterizedTest
151+
@ValueSource(ints = {0, 1, 42, 89545664,
152+
-1, -42, -89545664,
153+
Integer.MAX_VALUE - (1 << 10), Integer.MAX_VALUE - 42, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,
154+
Integer.MIN_VALUE + (1 << 10), Integer.MIN_VALUE + 42, Integer.MIN_VALUE + 1, Integer.MIN_VALUE})
155+
@MethodSource
156+
void testOfUnsignedInt(int x) {
157+
final DD dd = DD.ofUnsigned(x);
158+
Assertions.assertTrue(dd.hi() >= 0, "x hi should be positive");
159+
final double expected = Integer.toUnsignedLong(x);
160+
Assertions.assertEquals(expected, dd.hi(), "x hi");
161+
Assertions.assertEquals(0, dd.lo(), "x lo");
162+
}
163+
164+
static int[] testOfUnsignedInt() {
165+
// Random
166+
return createRNG().ints(10).toArray();
167+
}
168+
148169
/**
149170
* Test conversion of an unsigned {@code long}.
150171
*/
@@ -172,9 +193,9 @@ void testOfUnsignedLong(long x) {
172193
Assertions.assertEquals(lo, dd.lo(), "x lo");
173194
}
174195

175-
static LongStream testOfUnsignedLong() {
196+
static long[] testOfUnsignedLong() {
176197
// Random
177-
return createRNG().longs(10);
198+
return createRNG().longs(10).toArray();
178199
}
179200

180201
@ParameterizedTest

src/changes/changes.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ If the output is not quite correct, check for invisible trailing spaces!
5757
New features, updates and bug fixes.
5858
">
5959
<action dev="aherbert" type="add">
60-
"DD": Allow creation from an unsigned long value.
60+
"DD": Allow creation from an unsigned int or long value.
6161
</action>
6262
<action dev="aherbert" type="add" issue="NUMBERS-208">
6363
"Selection": Add support for selection from a long array.

0 commit comments

Comments
 (0)