Make withSign(NaN) behave as in JVM

#KT-4900

Where only the sign of the result is undefined, but the absolute value is unchanged.
This commit is contained in:
Ilya Gorbunov
2017-08-31 20:07:57 +03:00
parent 132f2f88c2
commit 480d4a0093
3 changed files with 15 additions and 6 deletions
+5 -5
View File
@@ -463,11 +463,11 @@ public inline val Double.sign: Double get() = nativeMath.sign(this)
* If [sign] is `NaN` the sign of the result is undefined. * If [sign] is `NaN` the sign of the result is undefined.
*/ */
@SinceKotlin("1.2") @SinceKotlin("1.2")
public fun Double.withSign(sign: Double): Double = public fun Double.withSign(sign: Double): Double {
this.absoluteValue * when(sign) { val thisSignBit = js("Kotlin").doubleSignBit(this).unsafeCast<Int>()
0.0 -> sign(1 / sign) val newSignBit = js("Kotlin").doubleSignBit(sign).unsafeCast<Int>()
else -> sign(sign) return if (thisSignBit == newSignBit) this else -this
} }
/** /**
* Returns this value with the sign bit same as of the [sign] value. * Returns this value with the sign bit same as of the [sign] value.
+6
View File
@@ -83,6 +83,12 @@ function imul(a, b) {
bufInt32[0] = value; bufInt32[0] = value;
return bufFloat32[0]; return bufFloat32[0];
}; };
// returns zero value for number with positive sign bit and non-zero value for number with negative sign bit.
Kotlin.doubleSignBit = function(value) {
bufFloat64[0] = value;
return bufInt32[1] & 0x80000000;
}
})(); })();
+4 -1
View File
@@ -301,7 +301,7 @@ class DoubleMathTest {
for (b in allValues) { for (b in allValues) {
val r = a.withSign(b) val r = a.withSign(b)
assertEquals(a.absoluteValue, r.absoluteValue) assertEquals(a.absoluteValue, r.absoluteValue)
assertEquals(b.sign, r.sign) assertEquals(b.sign, r.sign, "expected $a with sign bit of $b to have sign ${b.sign}")
} }
val rp0 = a.withSign(0.0) val rp0 = a.withSign(0.0)
@@ -315,6 +315,9 @@ class DoubleMathTest {
val ri = a.withSign(-1) val ri = a.withSign(-1)
assertEquals(-1.0, ri.sign) assertEquals(-1.0, ri.sign)
assertEquals(a.absoluteValue, ri.absoluteValue) assertEquals(a.absoluteValue, ri.absoluteValue)
val rn = a.withSign(Double.NaN)
assertEquals(a.absoluteValue, rn.absoluteValue)
} }
} }