Skip to content

Commit b26f6cc

Browse files
committed
2 parents 347f8c1 + 659f95b commit b26f6cc

2 files changed

Lines changed: 39 additions & 4 deletions

File tree

src/main/java/tech/units/indriya/function/DefaultNumberSystem.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
*/
5050
public class DefaultNumberSystem implements NumberSystem {
5151

52+
static final double MAX_LONG_AS_DOUBLE = Long.MAX_VALUE;
53+
static final double MIN_LONG_AS_DOUBLE = Long.MIN_VALUE;
54+
5255
/**
5356
* In order of increasing number type 'widening'.
5457
*/
@@ -163,7 +166,7 @@ static NumberType valueOf(final Number number) {
163166
/**
164167
* Whether given {@link Number} is ZERO.
165168
* @param number - must be of type {@link #getType()}
166-
* @apiNote For class internal use only,
169+
* @apiNote For class internal use only,
167170
* such that we have control over the number's type that gets passed in.
168171
*/
169172
boolean isZero(Number number) {
@@ -466,8 +469,22 @@ public Number narrow(final Number number) {
466469
if(!Double.isFinite(doubleValue)) {
467470
throw unsupportedNumberValue(doubleValue);
468471
}
469-
if(doubleValue % 1 == 0 && !isZero(number)) {
472+
if(doubleValue == 0) {
473+
return 0;
474+
}
475+
if(doubleValue % 1 == 0) {
470476
// double represents an integer other than zero
477+
478+
// narrow to long if possible
479+
if(MIN_LONG_AS_DOUBLE <= doubleValue && doubleValue <= MAX_LONG_AS_DOUBLE) {
480+
long longValue = (long) doubleValue;
481+
482+
// further narrow to int if possible
483+
if(Integer.MIN_VALUE <= longValue && longValue <= Integer.MAX_VALUE) {
484+
return (int) longValue;
485+
}
486+
return longValue;
487+
}
471488
return narrow(BigDecimal.valueOf(doubleValue));
472489
}
473490
return number;
@@ -781,7 +798,7 @@ private Number addWideAndNarrow(
781798
private Number multiplyWideAndNarrow(
782799
final NumberType wideType, final Number wide,
783800
final NumberType narrowType, final Number narrow) {
784-
801+
785802
// shortcut if any of the operands is zero.
786803
if (wideType.isZero(wide)
787804
|| narrowType.isZero(narrow)) {

src/test/java/tech/units/indriya/function/DefaultNumberSystemTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,18 @@
3939

4040
import javax.measure.quantity.Dimensionless;
4141

42+
import org.junit.jupiter.api.Assertions;
4243
import org.junit.jupiter.api.BeforeEach;
4344
import org.junit.jupiter.api.Named;
45+
import org.junit.jupiter.api.Test;
4446
import org.junit.jupiter.params.ParameterizedTest;
4547
import org.junit.jupiter.params.provider.Arguments;
4648
import org.junit.jupiter.params.provider.MethodSource;
4749

4850
import static org.junit.Assert.assertTrue;
51+
import static org.junit.jupiter.api.Assertions.assertEquals;
4952
import static org.junit.jupiter.api.Assertions.assertFalse;
53+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
5054

5155
import tech.units.indriya.AbstractUnit;
5256
import tech.units.indriya.ComparableQuantity;
@@ -212,7 +216,7 @@ static Stream<BigDecimal> provideNonFractionalBigDecimalSamples() {
212216
BigDecimal.valueOf(1),
213217
BigDecimal.valueOf(100, 2), // 100 * 10^-2 == 1
214218
BigDecimal.valueOf(1, -2), // 1 * 10^2 == 100
215-
new BigDecimal("1234.000") // trailing zeros, should not make this decimal a non integer
219+
new BigDecimal("1234.000") // trailing zeros, should not make this decimal a non integer
216220
);
217221
}
218222
@ParameterizedTest
@@ -316,4 +320,18 @@ static Stream<Number> provideZeroSamples() {
316320
);
317321
}
318322

323+
324+
// -- NARROW TESTS
325+
@Test
326+
void narrow() {
327+
assertInstanceOf(Integer.class, ns.narrow(0.0));
328+
assertInstanceOf(Integer.class, ns.narrow(1.0));
329+
assertInstanceOf(Integer.class, ns.narrow((double) Integer.MIN_VALUE));
330+
assertInstanceOf(Integer.class, ns.narrow((double) Integer.MAX_VALUE));
331+
assertInstanceOf(Long.class, ns.narrow(DefaultNumberSystem.MIN_LONG_AS_DOUBLE));
332+
assertInstanceOf(Long.class, ns.narrow(DefaultNumberSystem.MAX_LONG_AS_DOUBLE));
333+
// corner cases at the edge of the long range
334+
assertInstanceOf(BigInteger.class, ns.narrow(Math.nextDown(DefaultNumberSystem.MIN_LONG_AS_DOUBLE)));
335+
assertInstanceOf(BigInteger.class, ns.narrow(Math.nextUp(DefaultNumberSystem.MAX_LONG_AS_DOUBLE)));
336+
}
319337
}

0 commit comments

Comments
 (0)