diff --git a/src/commonMain/kotlin/ExactMath.kt b/src/commonMain/kotlin/ExactMath.kt index 39fc607..b7890b5 100644 --- a/src/commonMain/kotlin/ExactMath.kt +++ b/src/commonMain/kotlin/ExactMath.kt @@ -6,5 +6,8 @@ package dev.erikchristensen.javamath2kmp import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName +infix fun Int.plusExact(other: Long): Long = this.toLong() plusExact other +infix fun Int.minusExact(other: Long): Long = this.toLong() minusExact other + infix fun Long.plusExact(other: Int): Long = this plusExact other.toLong() infix fun Long.minusExact(other: Int): Long = this minusExact other.toLong() diff --git a/src/commonTest/kotlin/MathTest.kt b/src/commonTest/kotlin/MathTest.kt index bb8f189..a96ab01 100644 --- a/src/commonTest/kotlin/MathTest.kt +++ b/src/commonTest/kotlin/MathTest.kt @@ -49,59 +49,116 @@ class MathTest { } @Test - fun plusExact_throwsWhenAddingLongsCausesOverflow() { + fun plusExact_IntInt_throwsOnOverflow() { + assertFailsWith { Int.MAX_VALUE plusExact 1 } + assertFailsWith { Int.MAX_VALUE plusExact Int.MAX_VALUE } + assertFailsWith { Int.MIN_VALUE plusExact -1 } + assertFailsWith { Int.MIN_VALUE plusExact Int.MIN_VALUE } + } + + @Test + fun plusExact_IntInt_addsWhenResultFits() { + assertEquals(Int.MAX_VALUE, Int.MAX_VALUE - 1 plusExact 1) + assertEquals(Int.MIN_VALUE, Int.MIN_VALUE + 1 plusExact -1) + } + + @Test + fun plusExact_IntLong_throwsOnOverflow() { + assertFailsWith { 1 plusExact Long.MAX_VALUE } + assertFailsWith { Int.MAX_VALUE plusExact Long.MAX_VALUE } + assertFailsWith { -1 plusExact Long.MIN_VALUE } + assertFailsWith { Int.MIN_VALUE plusExact Long.MIN_VALUE } + } + + @Test + fun plusExact_IntLong_addsWhenResultFits() { + assertEquals(Int.MAX_VALUE.toLong(), Int.MAX_VALUE - 1 plusExact 1L) + assertEquals(Int.MIN_VALUE.toLong(), Int.MIN_VALUE + 1 plusExact -1L) + } + + @Test + fun plusExact_LongInt_throwsOnOverflow() { assertFailsWith { Long.MAX_VALUE plusExact 1 } + assertFailsWith { Long.MAX_VALUE plusExact Int.MAX_VALUE } + assertFailsWith { Long.MIN_VALUE plusExact -1 } + assertFailsWith { Long.MIN_VALUE plusExact Int.MIN_VALUE } + } + + @Test + fun plusExact_LongInt_addsWhenResultFits() { + assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 plusExact 1) + assertEquals(Long.MIN_VALUE, Long.MIN_VALUE + 1 plusExact -1) + } + + @Test + fun plusExact_LongLong_throwsOnOverflow() { + assertFailsWith { Long.MAX_VALUE plusExact 1L } + assertFailsWith { 1L plusExact Long.MAX_VALUE } + assertFailsWith { Long.MIN_VALUE plusExact -1L } + assertFailsWith { -1L plusExact Long.MIN_VALUE } assertFailsWith { Long.MAX_VALUE plusExact Long.MAX_VALUE } - assertFailsWith { Long.MIN_VALUE plusExact (-1) } assertFailsWith { Long.MIN_VALUE plusExact Long.MIN_VALUE } } @Test - fun plusExact_addsLongsWhenResultFits() { - assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 plusExact 1) - assertEquals(Long.MIN_VALUE, Long.MIN_VALUE + 1 plusExact (-1)) + fun plusExact_LongLong_addsWhenResultFits() { + assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 plusExact 1L) + assertEquals(Long.MIN_VALUE, Long.MIN_VALUE + 1 plusExact -1L) } @Test - fun plusExact_throwsWhenAddingIntsCausesOverflow() { - assertFailsWith { Int.MAX_VALUE plusExact 1 } - assertFailsWith { Int.MAX_VALUE plusExact Int.MAX_VALUE } - assertFailsWith { Int.MIN_VALUE plusExact (-1) } - assertFailsWith { Int.MIN_VALUE plusExact Int.MIN_VALUE } + fun minusExact_IntInt_throwsOnOverflow() { + assertFailsWith { Int.MIN_VALUE minusExact 1 } + assertFailsWith { Int.MIN_VALUE minusExact Int.MAX_VALUE } + assertFailsWith { Int.MAX_VALUE minusExact -1 } + assertFailsWith { Int.MAX_VALUE minusExact Int.MIN_VALUE } } @Test - fun plusExact_addsIntsWhenResultFits() { - assertEquals(Int.MAX_VALUE, Int.MAX_VALUE - 1 plusExact 1) - assertEquals(Int.MIN_VALUE, Int.MIN_VALUE + 1 plusExact (-1)) + fun minusExact_IntInt_subtractsWhenResultFits() { + assertEquals(Int.MIN_VALUE, Int.MIN_VALUE + 1 minusExact 1) + assertEquals(Int.MAX_VALUE, Int.MAX_VALUE - 1 minusExact -1) + } + + @Test + fun minusExact_IntLong_throwsOnOverflow() { + assertFailsWith { 0 minusExact Long.MIN_VALUE } + assertFailsWith { Long.MIN_VALUE minusExact Int.MAX_VALUE } + assertFailsWith { Long.MAX_VALUE minusExact -1 } + assertFailsWith { Long.MAX_VALUE minusExact Int.MIN_VALUE } } @Test - fun minusExact_throwsWhenSubtractingLongsCausesOverflow() { + fun minusExact_IntLong_subtractsWhenResultFits() { + assertEquals(Long.MIN_VALUE, -1 minusExact Long.MAX_VALUE) + } + + @Test + fun minusExact_LongInt_throwsOnOverflow() { assertFailsWith { Long.MIN_VALUE minusExact 1 } - assertFailsWith { Long.MIN_VALUE minusExact Long.MAX_VALUE } - assertFailsWith { Long.MAX_VALUE minusExact (-1) } - assertFailsWith { Long.MAX_VALUE minusExact Long.MIN_VALUE } + assertFailsWith { Long.MIN_VALUE minusExact Int.MAX_VALUE } + assertFailsWith { Long.MAX_VALUE minusExact -1 } + assertFailsWith { Long.MAX_VALUE minusExact Int.MIN_VALUE } } @Test - fun minusExact_subtractsLongsWhenResultFits() { + fun minusExact_LongInt_subtractsWhenResultFits() { assertEquals(Long.MIN_VALUE, Long.MIN_VALUE + 1 minusExact 1) - assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 minusExact (-1)) + assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 minusExact -1) } @Test - fun minusExact_throwsWhenSubtractingIntsCausesOverflow() { - assertFailsWith { Int.MIN_VALUE minusExact 1 } - assertFailsWith { Int.MIN_VALUE minusExact Int.MAX_VALUE } - assertFailsWith { Int.MAX_VALUE minusExact (-1) } - assertFailsWith { Int.MAX_VALUE minusExact Int.MIN_VALUE } + fun minusExact_LongLong_throwsOnOverflow() { + assertFailsWith { Long.MIN_VALUE minusExact 1L } + assertFailsWith { Long.MIN_VALUE minusExact Long.MAX_VALUE } + assertFailsWith { Long.MAX_VALUE minusExact -1L } + assertFailsWith { Long.MAX_VALUE minusExact Long.MIN_VALUE } } @Test - fun minusExact_subtractsIntsWhenResultFits() { - assertEquals(Int.MIN_VALUE, Int.MIN_VALUE + 1 minusExact 1) - assertEquals(Int.MAX_VALUE, Int.MAX_VALUE - 1 minusExact (-1)) + fun minusExact_LongLong_subtractsWhenResultFits() { + assertEquals(Long.MIN_VALUE, Long.MIN_VALUE + 1 minusExact 1L) + assertEquals(Long.MAX_VALUE, Long.MAX_VALUE - 1 minusExact -1L) } @Test @@ -110,7 +167,7 @@ class MathTest { assertFailsWith { Long.MAX_VALUE timesExact Long.MAX_VALUE } assertFailsWith { Long.MIN_VALUE timesExact Long.MIN_VALUE } assertFailsWith { Long.MIN_VALUE timesExact Long.MAX_VALUE } - assertFailsWith { Long.MIN_VALUE timesExact (-1) } + assertFailsWith { Long.MIN_VALUE timesExact -1 } } @Test @@ -127,7 +184,7 @@ class MathTest { assertFailsWith { Int.MAX_VALUE timesExact Int.MAX_VALUE } assertFailsWith { Int.MIN_VALUE timesExact Int.MIN_VALUE } assertFailsWith { Int.MIN_VALUE timesExact Int.MAX_VALUE } - assertFailsWith { Int.MIN_VALUE timesExact (-1) } + assertFailsWith { Int.MIN_VALUE timesExact -1 } } @Test