diff --git a/generators/builtins/primitives/WasmPrimitivesGenerator.kt b/generators/builtins/primitives/WasmPrimitivesGenerator.kt index 33abb5f4c98..c807ba3bc69 100644 --- a/generators/builtins/primitives/WasmPrimitivesGenerator.kt +++ b/generators/builtins/primitives/WasmPrimitivesGenerator.kt @@ -99,7 +99,7 @@ class WasmPrimitivesGenerator(writer: PrintWriter) : BasePrimitivesGenerator(wri } } "rem" -> when (thisKind) { - in PrimitiveType.floatingPoint -> "this - (wasm_${thisKind.prefixLowercase}_truncate(this / $parameterName) * $parameterName)" + in PrimitiveType.floatingPoint -> "wasm_${thisKind.prefixLowercase}_copysign(this - (wasm_${thisKind.prefixLowercase}_truncate(this / $parameterName) * $parameterName), this)" else -> return implementAsIntrinsic(thisKind, methodName) } else -> return implementAsIntrinsic(thisKind, methodName) diff --git a/libraries/stdlib/test/numbers/FloorDivModTest.kt b/libraries/stdlib/test/numbers/FloorDivModTest.kt index 8dc8a0a5218..83745d38043 100644 --- a/libraries/stdlib/test/numbers/FloorDivModTest.kt +++ b/libraries/stdlib/test/numbers/FloorDivModTest.kt @@ -34,6 +34,7 @@ class FloorDivModTest { check(10, 3, 3, 1) check(-10, 3, -4, 2) check(-10, -3, 3, -1) + check(-2, 2, -1, -0) val values = listOf(1, -1, 2, -2, 3, -3, Int.MIN_VALUE, Int.MAX_VALUE) for (a in values + 0) { for (b in values) { @@ -69,6 +70,7 @@ class FloorDivModTest { check(10, 3, 3, 1) check(-10, 3, -4, 2) check(-10, -3, 3, -1) + check(-2, 2, -1, -0) val values = listOf(1, -1, 2, -2, 3, -3, Long.MIN_VALUE, Long.MAX_VALUE) for (a in values + 0) { for (b in values) { @@ -104,6 +106,7 @@ class FloorDivModTest { check(10, 3, 3, 1) check(-10, 3, -4, 2) check(-10, -3, 3, -1) + check(-2, 2, -1, -0) val values = listOf(1, -1, 2, -2, 3, -3, Byte.MIN_VALUE, Byte.MAX_VALUE) for (a in values + 0) { for (b in values) { @@ -139,6 +142,7 @@ class FloorDivModTest { check(10, 3, 3, 1) check(-10, 3, -4, 2) check(-10, -3, 3, -1) + check(-2, 2, -1, -0) val values = listOf(1, -1, 2, -2, 3, -3, Short.MIN_VALUE, Short.MAX_VALUE) for (a in values + 0) { for (b in values) { @@ -221,6 +225,7 @@ class FloorDivModTest { check(10.125, 0.5, 0.125) check(-10.125, 0.5, 0.375) check(-10.125, -0.5, -0.125) + check(-2.0, 2.0, -0.0) val large = 2.0.pow(53) check(0.025, large, 0.025) check(-0.025, large, expectedMod = large) @@ -259,6 +264,7 @@ class FloorDivModTest { check(10.125f, 0.5f, 0.125f) check(-10.125f, 0.5f, 0.375f) check(-10.125f, -0.5f, -0.125f) + check(-2.0f, 2.0f, -0.0f) val large = 2.0f.pow(53) check(0.025f, large, 0.025f) check(-0.025f, large, expectedMod = large) diff --git a/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt b/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt index 659741c7e87..353478c1a9e 100644 --- a/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt @@ -2155,7 +2155,7 @@ public class Float private constructor(private val value: Float) : Number(), Com @SinceKotlin("1.1") @kotlin.internal.IntrinsicConstEvaluation public operator fun rem(other: Float): Float = - this - (wasm_f32_truncate(this / other) * other) + wasm_f32_copysign(this - (wasm_f32_truncate(this / other) * other), this) /** * Calculates the remainder of truncating division of this value (dividend) by the other value (divisor). @@ -2565,7 +2565,7 @@ public class Double private constructor(private val value: Double) : Number(), C @SinceKotlin("1.1") @kotlin.internal.IntrinsicConstEvaluation public operator fun rem(other: Double): Double = - this - (wasm_f64_truncate(this / other) * other) + wasm_f64_copysign(this - (wasm_f64_truncate(this / other) * other), this) /** * Returns this value incremented by one.