Handle non-finite real/decimal arithmetic
This commit is contained in:
1 parent
f845213332
commit
850efedb72
5 files changed
+215
-26
No files matched your search
@@ -5460,4 +5460,34 @@ class ScriptTest {
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun testFromCalcrus1() = runTest {
|
||||
// eval($$"""
|
||||
// import lyng.decimal
|
||||
// var x = 7.0.d
|
||||
// // глубина по звуку падения
|
||||
// val m = 1 // kg
|
||||
// val d = 0.06 // 6 cm
|
||||
// val c = 340 // скор. звука
|
||||
// val g = 9.82
|
||||
// var cnt = 0
|
||||
// var h = 0.0
|
||||
// var t = x
|
||||
// var message = ""
|
||||
//
|
||||
// while(true){
|
||||
// val h0 = 0
|
||||
// h = c*c/h*(1 + g*t/c -sqrt(1+2*g*t/c))
|
||||
// message = "iter ${cnt++}"
|
||||
// if( cnt > 100 ) {
|
||||
// message= "ошибка"
|
||||
// break 0
|
||||
// }
|
||||
// x = h
|
||||
// if( abs(h-h0)/h > 0.08 ) break h
|
||||
// }
|
||||
// println(x)
|
||||
// """.trimIndent())
|
||||
// }
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package net.sergeych.lyng
|
||||
|
||||
import com.ionspin.kotlin.bignum.decimal.BigDecimal
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.lyng.obj.ObjException
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
@@ -77,6 +78,94 @@ class DecimalModuleTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDecimalModuleMixedRealOperators() = runTest {
|
||||
val scope = Script.newScope()
|
||||
scope.eval(
|
||||
"""
|
||||
import lyng.decimal
|
||||
|
||||
assertEquals(3.5.d, 1.5 + 2.d)
|
||||
assertEquals(3.5.d, 2.d + 1.5)
|
||||
assertEquals(1.5.d, 3.5 - 2.d)
|
||||
assertEquals(1.5.d, 3.5.d - 2.0)
|
||||
assertEquals(7.d, 3.5 * 2.d)
|
||||
assertEquals(7.d, 3.5.d * 2.0)
|
||||
assertEquals(1.75.d, 3.5 / 2.d)
|
||||
assertEquals(1.75.d, 3.5.d / 2.0)
|
||||
assert(1.5 < 2.d)
|
||||
assert(2.5.d > 2.0)
|
||||
assert(2.5 == 2.5.d)
|
||||
assert(2.5.d == 2.5)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMixedRealDecimalNonFiniteResultsStayReal() = runTest {
|
||||
val scope = Script.newScope()
|
||||
scope.eval(
|
||||
"""
|
||||
import lyng.decimal
|
||||
|
||||
val inf1 = 1.0 / 0.d
|
||||
val inf2 = 1.d / 0.0
|
||||
val inf3 = (1.0 / 0.0) * 2.d
|
||||
val negInf = -1.d / 0.0
|
||||
val nan1 = 0.0 / 0.d
|
||||
val nan2 = (0.0 / 0.0) + 1.d
|
||||
|
||||
assert(inf1 is Real)
|
||||
assert(inf2 is Real)
|
||||
assert(inf3 is Real)
|
||||
assert(negInf is Real)
|
||||
assert(nan1 is Real)
|
||||
assert(nan2 is Real)
|
||||
|
||||
assertEquals("Infinity", inf1.toString())
|
||||
assertEquals("Infinity", inf2.toString())
|
||||
assertEquals("Infinity", inf3.toString())
|
||||
assertEquals("-Infinity", negInf.toString())
|
||||
assertEquals("NaN", nan1.toString())
|
||||
assertEquals("NaN", nan2.toString())
|
||||
|
||||
assert(inf1 > 999999999.d)
|
||||
assert(negInf < -999999999.d)
|
||||
assert(!(nan1 == 1.d))
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDecimalRejectsExplicitNonFiniteRealConversions() = runTest {
|
||||
val scope = Script.newScope()
|
||||
val ex1 = assertFailsWith<ExecutionError> {
|
||||
scope.eval(
|
||||
"""
|
||||
import lyng.decimal
|
||||
(1.0 / 0.0).d
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
val ex2 = assertFailsWith<ExecutionError> {
|
||||
scope.eval(
|
||||
"""
|
||||
import lyng.decimal
|
||||
Decimal.fromReal(0.0 / 0.0)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
"cannot convert non-finite Real to Decimal: Infinity",
|
||||
(ex1.errorObject as ObjException).message.value
|
||||
)
|
||||
assertEquals(
|
||||
"cannot convert non-finite Real to Decimal: NaN",
|
||||
(ex2.errorObject as ObjException).message.value
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDecimalDivisionUsesDefaultContext() = runTest {
|
||||
val scope = Script.newScope()
|
||||
|
||||
Reference in new issue
Block a user