classlib: distinguish between +0 and -0 in double stringifier, improve copySign implementation

This commit is contained in:
Ivan Hetman 2023-09-25 16:56:43 +03:00 committed by GitHub
parent 05f50afa8d
commit 603d7f1f88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 38 deletions

View File

@ -194,18 +194,20 @@ class TAbstractStringBuilder implements TSerializable, TCharSequence {
protected TAbstractStringBuilder insert(int target, float value) {
if (value == 0) {
insertSpace(target, target + 3);
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
} else if (value == -0) {
insertSpace(target, target + 4);
buffer[target++] = '-';
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
if (1 / value == Float.POSITIVE_INFINITY) {
insertSpace(target, target + 3);
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
} else {
insertSpace(target, target + 4);
buffer[target++] = '-';
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
}
} else if (Float.isNaN(value)) {
insertSpace(target, target + 3);
buffer[target++] = 'N';
@ -330,18 +332,20 @@ class TAbstractStringBuilder implements TSerializable, TCharSequence {
protected TAbstractStringBuilder insert(int target, double value) {
if (value == 0) {
insertSpace(target, target + 3);
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
} else if (value == -0) {
insertSpace(target, target + 4);
buffer[target++] = '-';
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
if (1 / value == Double.POSITIVE_INFINITY) {
insertSpace(target, target + 3);
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
} else {
insertSpace(target, target + 4);
buffer[target++] = '-';
buffer[target++] = '0';
buffer[target++] = '.';
buffer[target++] = '0';
return this;
}
} else if (Double.isNaN(value)) {
insertSpace(target, target + 3);
buffer[target++] = 'N';

View File

@ -344,29 +344,25 @@ public final class TMath extends TObject {
}
public static float copySign(float magnitude, float sign) {
if (sign == 0 || sign == -0) {
return sign;
}
return (sign > 0) == (magnitude > 0) ? magnitude : -magnitude;
return Float.intBitsToFloat((Float.floatToRawIntBits(sign) & Integer.MIN_VALUE)
| (Float.floatToRawIntBits(magnitude) & Integer.MAX_VALUE));
}
public static double copySign(double magnitude, double sign) {
if (sign == 0 || sign == -0) {
return sign;
}
return (sign > 0) == (magnitude > 0) ? magnitude : -magnitude;
return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) & Long.MIN_VALUE)
| (Double.doubleToRawLongBits(magnitude) & Long.MAX_VALUE));
}
public static int getExponent(double d) {
long bits = TDouble.doubleToLongBits(d);
long bits = TDouble.doubleToRawLongBits(d);
int exponent = (int) ((bits >> 52) & 0x7FF);
return exponent - 1023;
}
public static int getExponent(float f) {
int bits = TFloat.floatToIntBits(f);
int exponent = (bits >> 23) & 0xF;
return exponent + 128;
int bits = TFloat.floatToRawIntBits(f);
int exponent = (bits >> 23) & 0xFF;
return exponent - 127;
}
public static double nextAfter(double start, double direction) {

View File

@ -94,6 +94,20 @@ public class MathTest {
assertEquals(Float.valueOf(1), Float.valueOf(Math.signum(Float.POSITIVE_INFINITY)));
}
@Test
public void copySignWorks() {
assertEquals(Double.valueOf(1.0), Double.valueOf(Math.copySign(1.0, 0.0)));
assertEquals(Double.valueOf(-1.0), Double.valueOf(Math.copySign(1.0, -0.0)));
assertEquals(Double.valueOf(1.0), Double.valueOf(Math.copySign(1.0, Double.NaN)));
assertEquals(Double.valueOf(Double.NaN), Double.valueOf(Math.copySign(Double.NaN, -1.0)));
assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), Double.valueOf(Math.copySign(Double.NEGATIVE_INFINITY, 1.0)));
assertEquals(Float.valueOf(1.0f), Float.valueOf(Math.copySign(1.0f, 0.0f)));
assertEquals(Float.valueOf(-1.0f), Float.valueOf(Math.copySign(1.0f, -0.0f)));
assertEquals(Float.valueOf(1.0f), Float.valueOf(Math.copySign(1.0f, Float.NaN)));
assertEquals(Float.valueOf(Float.NaN), Float.valueOf(Math.copySign(Float.NaN, -1.0f)));
assertEquals(Float.valueOf(Float.POSITIVE_INFINITY), Float.valueOf(Math.copySign(Float.NEGATIVE_INFINITY, 1.0f)));
}
@Test
public void roundWorks() {
assertEquals(1, Math.round(1.3));
@ -133,4 +147,20 @@ public class MathTest {
assertEquals(Double.valueOf(Double.longBitsToDouble(Double.doubleToLongBits(Double.NEGATIVE_INFINITY) - 1)),
Double.valueOf(Math.nextUp(Double.NEGATIVE_INFINITY)));
}
@Test
public void exponentWorks() {
assertEquals(0, Math.getExponent(1.0f));
assertEquals(-127, Math.getExponent(Float.MIN_VALUE));
assertEquals(127, Math.getExponent(Float.MAX_VALUE));
assertEquals(128, Math.getExponent(Float.POSITIVE_INFINITY));
assertEquals(128, Math.getExponent(Float.NEGATIVE_INFINITY));
assertEquals(128, Math.getExponent(Float.NaN));
assertEquals(0, Math.getExponent(1.0));
assertEquals(-1023, Math.getExponent(Double.MIN_VALUE));
assertEquals(1023, Math.getExponent(Double.MAX_VALUE));
assertEquals(1024, Math.getExponent(Double.POSITIVE_INFINITY));
assertEquals(1024, Math.getExponent(Double.NEGATIVE_INFINITY));
assertEquals(1024, Math.getExponent(Double.NaN));
}
}

View File

@ -78,13 +78,14 @@ public class StringBuilderTest {
.append(" ").append(1200f)
.append(" ").append(0.023f)
.append(" ").append(0f)
.append(" ").append(-0.0f)
.append(" ").append(1f)
.append(" ").append(Float.NaN)
.append(" ").append(Float.POSITIVE_INFINITY)
.append(" ").append(Float.NEGATIVE_INFINITY);
assertEquals("1.234E25 9.8765E30 -1.234E25 -9.8765E30 3.402823E38"
+ " 1.234E-25 9.8764E-30 -1.234E-25 -9.8764E-30 1.17549E-38"
+ " 1200.0 0.023 0.0 1.0 NaN Infinity -Infinity", sb.toString());
+ " 1200.0 0.023 0.0 -0.0 1.0 NaN Infinity -Infinity", sb.toString());
}
@Test
@ -107,6 +108,7 @@ public class StringBuilderTest {
.append(" ").append(1200.0)
.append(" ").append(0.023)
.append(" ").append(0.0)
.append(" ").append(-0.0)
.append(" ").append(1.0)
.append(" ").append(Double.NaN)
.append(" ").append(Double.POSITIVE_INFINITY)
@ -114,7 +116,7 @@ public class StringBuilderTest {
assertEquals("1.23456789E150 10.0 20.0 100.0 1000.0 0.1 0.01 1.0E20 2.0E20 1.0E-12"
+ " -1.23456789E150 1.23456789E-150 1.79769313486231E308 3.0E-308"
+ " 1200.0 0.023"
+ " 0.0 1.0 NaN Infinity -Infinity", sb.toString());
+ " 0.0 -0.0 1.0 NaN Infinity -Infinity", sb.toString());
}
@Test