Skip to content

Commit

Permalink
Fix decimal INF, NEG_INF, NAN values
Browse files Browse the repository at this point in the history
  • Loading branch information
alex268 committed Oct 1, 2024
1 parent 7e303cb commit 6735da1
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 30 deletions.
39 changes: 24 additions & 15 deletions table/src/main/java/tech/ydb/table/values/DecimalValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public long getLow() {
}

public boolean isInf() {
return this == INF;
return this.high == INF.high && this.low == INF.low;
}

public boolean isNegativeInf() {
return this == NEG_INF;
return this.high == NEG_INF.high && this.low == NEG_INF.low;
}

public boolean isNan() {
return this == NAN;
return this.high == NAN.high && this.low == NAN.low;
}

public boolean isZero() {
Expand Down Expand Up @@ -273,19 +273,28 @@ private static long getLongBe(byte[] buf, int from, int to) {
}

private static boolean isNan(long high, long low) {
return NAN.getHigh() == high && NAN.getLow() == low;
return NAN.high == high && NAN.low == low;
}

private static boolean isInf(long high, long low) {
return high > INF.getHigh() ||
(high == INF.getHigh() && Long.compareUnsigned(low, INF.getLow()) >= 0);
return high > INF.high || (high == INF.high && Long.compareUnsigned(low, INF.low) >= 0);
}

private static boolean isNegInf(long high, long low) {
return high < NEG_INF.getHigh() ||
(high == NEG_INF.getHigh() && Long.compareUnsigned(low, NEG_INF.getLow()) <= 0);
return high < NEG_INF.high || (high == NEG_INF.high && Long.compareUnsigned(low, NEG_INF.low) <= 0);
}

private static DecimalValue newNan(DecimalType type) {
return new DecimalValue(type, NAN.high, NAN.low);
}

private static DecimalValue newInf(DecimalType type) {
return new DecimalValue(type, INF.high, INF.low);
}

private static DecimalValue newNegInf(DecimalType type) {
return new DecimalValue(type, NEG_INF.high, NEG_INF.low);
}
static DecimalValue fromUnscaledLong(DecimalType type, long value) {
if (value == 0) {
return new DecimalValue(type, 0, 0);
Expand All @@ -300,15 +309,15 @@ static DecimalValue fromBits(DecimalType type, long high, long low) {
}

if (isNan(high, low)) {
return NAN;
return newNan(type);
}

if (isInf(high, low)) {
return INF;
return newInf(type);
}

if (isNegInf(high, low)) {
return NEG_INF;
return newNegInf(type);
}

return new DecimalValue(type, high, low);
Expand All @@ -322,7 +331,7 @@ static DecimalValue fromUnscaledBigInteger(DecimalType type, BigInteger value) {

boolean negative = value.signum() < 0;
if (bitLength > 128) {
return negative ? DecimalValue.NEG_INF : DecimalValue.INF;
return negative ? newNegInf(type) : newInf(type);
}

byte[] buf = value.abs().toByteArray();
Expand Down Expand Up @@ -358,7 +367,7 @@ private static DecimalValue fromUnsignedLong(DecimalType type, boolean positive,
lowHi = lowHi & HALF_LONG_MASK;
if ((high & LONG_SIGN_BIT) != 0) {
// number is too big, return infinite
return positive ? INF : NEG_INF;
return positive ? newInf(type) : newNegInf(type);
}
}

Expand Down Expand Up @@ -408,11 +417,11 @@ static DecimalValue fromString(DecimalType type, String value) {
char c3 = value.charAt(cursor + 2);

if ((c1 == 'i' || c1 == 'I') && (c2 == 'n' || c2 == 'N') || (c3 == 'f' || c3 == 'F')) {
return negative ? DecimalValue.NEG_INF : DecimalValue.INF;
return negative ? newNegInf(type) : newInf(type);
}

if ((c1 == 'n' || c1 == 'N') && (c2 == 'a' || c2 == 'A') || (c3 == 'n' || c3 == 'N')) {
return DecimalValue.NAN;
return new DecimalValue(type, NAN.high, NAN.low);
}
}

Expand Down
60 changes: 45 additions & 15 deletions table/src/test/java/tech/ydb/table/values/DecimalValueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,22 @@ public void inf() {
DecimalValue value = type.newValue(inf);
Assert.assertTrue(value.isInf());
Assert.assertFalse(value.isNegative());
Assert.assertSame(DecimalValue.INF, value);
Assert.assertEquals(DecimalValue.INF, value);
inf = inf.add(k);
}
}

@Test
public void infDefaulttype() {
DecimalType type = DecimalType.getDefault();
BigInteger inf = BigInteger.TEN.pow(DecimalType.MAX_PRECISION);
BigInteger k = BigInteger.valueOf(0x10000000_00000000L);

for (int i = 0; i < 100; i++) {
DecimalValue value = type.newValue(inf);
Assert.assertTrue(value.isInf());
Assert.assertFalse(value.isNegative());
Assert.assertNotEquals(DecimalValue.INF, value);
inf = inf.add(k);
}
}
Expand All @@ -95,7 +110,22 @@ public void negativeInf() {
DecimalValue value = type.newValue(inf);
Assert.assertTrue(value.isNegativeInf());
Assert.assertTrue(value.isNegative());
Assert.assertSame(DecimalValue.NEG_INF, value);
Assert.assertEquals(DecimalValue.NEG_INF, value);
inf = inf.subtract(k);
}
}

@Test
public void negativeInfDefaultType() {
DecimalType type = DecimalType.getDefault();
BigInteger inf = BigInteger.TEN.negate().pow(DecimalType.MAX_PRECISION);
BigInteger k = BigInteger.valueOf(0x10000000_00000000L);

for (int i = 0; i < 100; i++) {
DecimalValue value = type.newValue(inf);
Assert.assertTrue(value.isNegativeInf());
Assert.assertTrue(value.isNegative());
Assert.assertNotEquals(DecimalValue.NEG_INF, value);
inf = inf.subtract(k);
}
}
Expand Down Expand Up @@ -126,19 +156,19 @@ public void zero() {
public void ofString() {
DecimalType t = DecimalType.getDefault();

Assert.assertSame(DecimalValue.INF, t.newValue("inf"));
Assert.assertSame(DecimalValue.INF, t.newValue("Inf"));
Assert.assertSame(DecimalValue.INF, t.newValue("INF"));
Assert.assertSame(DecimalValue.INF, t.newValue("+inf"));
Assert.assertSame(DecimalValue.INF, t.newValue("+Inf"));
Assert.assertSame(DecimalValue.INF, t.newValue("+INF"));
Assert.assertSame(DecimalValue.NEG_INF, t.newValue("-inf"));
Assert.assertSame(DecimalValue.NEG_INF, t.newValue("-Inf"));
Assert.assertSame(DecimalValue.NEG_INF, t.newValue("-INF"));
Assert.assertSame(DecimalValue.NAN, t.newValue("nan"));
Assert.assertSame(DecimalValue.NAN, t.newValue("Nan"));
Assert.assertSame(DecimalValue.NAN, t.newValue("NaN"));
Assert.assertSame(DecimalValue.NAN, t.newValue("NAN"));
Assert.assertTrue(t.newValue("inf").isInf());
Assert.assertTrue(t.newValue("Inf").isInf());
Assert.assertTrue(t.newValue("INF").isInf());
Assert.assertTrue(t.newValue("+inf").isInf());
Assert.assertTrue(t.newValue("+Inf").isInf());
Assert.assertTrue(t.newValue("+INF").isInf());
Assert.assertTrue(t.newValue("-inf").isNegativeInf());
Assert.assertTrue(t.newValue("-Inf").isNegativeInf());
Assert.assertTrue(t.newValue("-INF").isNegativeInf());
Assert.assertTrue(t.newValue("nan").isNan());
Assert.assertTrue(t.newValue("Nan").isNan());
Assert.assertTrue(t.newValue("NaN").isNan());
Assert.assertTrue(t.newValue("NAN").isNan());

Assert.assertTrue(t.newValue("0").isZero());
Assert.assertTrue(t.newValue("00").isZero());
Expand Down

0 comments on commit 6735da1

Please sign in to comment.