Fix numeric fast-paths for Obj arithmetic
This commit is contained in:
parent
6220e982a0
commit
afbd6e45b9
@ -871,14 +871,21 @@ class CmdAddObj(internal val a: Int, internal val b: Int, internal val dst: Int)
|
|||||||
frame.setInt(dst, frame.frame.getInt(la) + frame.frame.getInt(lb))
|
frame.setInt(dst, frame.frame.getInt(la) + frame.frame.getInt(lb))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ta == SlotType.REAL.code || tb == SlotType.REAL.code) {
|
val aNumeric = ta == SlotType.INT.code || ta == SlotType.REAL.code
|
||||||
|
val bNumeric = tb == SlotType.INT.code || tb == SlotType.REAL.code
|
||||||
|
if (aNumeric && bNumeric && (ta == SlotType.REAL.code || tb == SlotType.REAL.code)) {
|
||||||
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
||||||
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
||||||
frame.setReal(dst, av + bv)
|
frame.setReal(dst, av + bv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.setObj(dst, frame.slotToObj(a).plus(frame.ensureScope(), frame.slotToObj(b)))
|
val result = frame.slotToObj(a).plus(frame.ensureScope(), frame.slotToObj(b))
|
||||||
|
when (result) {
|
||||||
|
is ObjInt -> frame.setInt(dst, result.value)
|
||||||
|
is ObjReal -> frame.setReal(dst, result.value)
|
||||||
|
else -> frame.setObj(dst, result)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -895,14 +902,21 @@ class CmdSubObj(internal val a: Int, internal val b: Int, internal val dst: Int)
|
|||||||
frame.setInt(dst, frame.frame.getInt(la) - frame.frame.getInt(lb))
|
frame.setInt(dst, frame.frame.getInt(la) - frame.frame.getInt(lb))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ta == SlotType.REAL.code || tb == SlotType.REAL.code) {
|
val aNumeric = ta == SlotType.INT.code || ta == SlotType.REAL.code
|
||||||
|
val bNumeric = tb == SlotType.INT.code || tb == SlotType.REAL.code
|
||||||
|
if (aNumeric && bNumeric && (ta == SlotType.REAL.code || tb == SlotType.REAL.code)) {
|
||||||
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
||||||
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
||||||
frame.setReal(dst, av - bv)
|
frame.setReal(dst, av - bv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.setObj(dst, frame.slotToObj(a).minus(frame.ensureScope(), frame.slotToObj(b)))
|
val result = frame.slotToObj(a).minus(frame.ensureScope(), frame.slotToObj(b))
|
||||||
|
when (result) {
|
||||||
|
is ObjInt -> frame.setInt(dst, result.value)
|
||||||
|
is ObjReal -> frame.setReal(dst, result.value)
|
||||||
|
else -> frame.setObj(dst, result)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -919,14 +933,21 @@ class CmdMulObj(internal val a: Int, internal val b: Int, internal val dst: Int)
|
|||||||
frame.setInt(dst, frame.frame.getInt(la) * frame.frame.getInt(lb))
|
frame.setInt(dst, frame.frame.getInt(la) * frame.frame.getInt(lb))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ta == SlotType.REAL.code || tb == SlotType.REAL.code) {
|
val aNumeric = ta == SlotType.INT.code || ta == SlotType.REAL.code
|
||||||
|
val bNumeric = tb == SlotType.INT.code || tb == SlotType.REAL.code
|
||||||
|
if (aNumeric && bNumeric && (ta == SlotType.REAL.code || tb == SlotType.REAL.code)) {
|
||||||
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
||||||
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
||||||
frame.setReal(dst, av * bv)
|
frame.setReal(dst, av * bv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.setObj(dst, frame.slotToObj(a).mul(frame.ensureScope(), frame.slotToObj(b)))
|
val result = frame.slotToObj(a).mul(frame.ensureScope(), frame.slotToObj(b))
|
||||||
|
when (result) {
|
||||||
|
is ObjInt -> frame.setInt(dst, result.value)
|
||||||
|
is ObjReal -> frame.setReal(dst, result.value)
|
||||||
|
else -> frame.setObj(dst, result)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -943,14 +964,21 @@ class CmdDivObj(internal val a: Int, internal val b: Int, internal val dst: Int)
|
|||||||
frame.setInt(dst, frame.frame.getInt(la) / frame.frame.getInt(lb))
|
frame.setInt(dst, frame.frame.getInt(la) / frame.frame.getInt(lb))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ta == SlotType.REAL.code || tb == SlotType.REAL.code) {
|
val aNumeric = ta == SlotType.INT.code || ta == SlotType.REAL.code
|
||||||
|
val bNumeric = tb == SlotType.INT.code || tb == SlotType.REAL.code
|
||||||
|
if (aNumeric && bNumeric && (ta == SlotType.REAL.code || tb == SlotType.REAL.code)) {
|
||||||
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
||||||
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
||||||
frame.setReal(dst, av / bv)
|
frame.setReal(dst, av / bv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.setObj(dst, frame.slotToObj(a).div(frame.ensureScope(), frame.slotToObj(b)))
|
val result = frame.slotToObj(a).div(frame.ensureScope(), frame.slotToObj(b))
|
||||||
|
when (result) {
|
||||||
|
is ObjInt -> frame.setInt(dst, result.value)
|
||||||
|
is ObjReal -> frame.setReal(dst, result.value)
|
||||||
|
else -> frame.setObj(dst, result)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -967,14 +995,21 @@ class CmdModObj(internal val a: Int, internal val b: Int, internal val dst: Int)
|
|||||||
frame.setInt(dst, frame.frame.getInt(la) % frame.frame.getInt(lb))
|
frame.setInt(dst, frame.frame.getInt(la) % frame.frame.getInt(lb))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ta == SlotType.REAL.code || tb == SlotType.REAL.code) {
|
val aNumeric = ta == SlotType.INT.code || ta == SlotType.REAL.code
|
||||||
|
val bNumeric = tb == SlotType.INT.code || tb == SlotType.REAL.code
|
||||||
|
if (aNumeric && bNumeric && (ta == SlotType.REAL.code || tb == SlotType.REAL.code)) {
|
||||||
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
val av = if (ta == SlotType.REAL.code) frame.frame.getReal(la) else frame.frame.getInt(la).toDouble()
|
||||||
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
val bv = if (tb == SlotType.REAL.code) frame.frame.getReal(lb) else frame.frame.getInt(lb).toDouble()
|
||||||
frame.setReal(dst, av % bv)
|
frame.setReal(dst, av % bv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.setObj(dst, frame.slotToObj(a).mod(frame.ensureScope(), frame.slotToObj(b)))
|
val result = frame.slotToObj(a).mod(frame.ensureScope(), frame.slotToObj(b))
|
||||||
|
when (result) {
|
||||||
|
is ObjInt -> frame.setInt(dst, result.value)
|
||||||
|
is ObjReal -> frame.setReal(dst, result.value)
|
||||||
|
else -> frame.setObj(dst, result)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,4 +96,54 @@ class TypesTest {
|
|||||||
assertNotEquals(Point(0,1), p3)
|
assertNotEquals(Point(0,1), p3)
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNumericInference() = runTest {
|
||||||
|
eval("""
|
||||||
|
val x = 1
|
||||||
|
var y = 2.0
|
||||||
|
assert( x is Int )
|
||||||
|
assert( y is Real )
|
||||||
|
assert( x + y is Real )
|
||||||
|
assert( abs(x+y) is Real )
|
||||||
|
assert( abs(x/y) is Real )
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun testNumericInferenceBug1() = runTest {
|
||||||
|
eval("""
|
||||||
|
fun findSumLimit(f) {
|
||||||
|
var sum = 0.0
|
||||||
|
for( n in 1..100 ) {
|
||||||
|
val s0 = sum
|
||||||
|
sum += f(n)
|
||||||
|
assert( sum is Real )
|
||||||
|
assert( s0 is Real )
|
||||||
|
val delta = abs(sum - s0) / abs(sum)
|
||||||
|
assert( delta is Real )
|
||||||
|
println("abs(%g - %g) = %g"(sum, s0, abs(sum-s0)))
|
||||||
|
if( s0 != 0 )
|
||||||
|
assert( abs(sum-s0) < abs(sum) )
|
||||||
|
println("abs(%g) = %g"(sum, abs(sum)))
|
||||||
|
println( "delta calc: %g"(delta) )
|
||||||
|
// if( n > 3 ) assert( delta < 1.0 )
|
||||||
|
if( delta < 1.0e-4 ) {
|
||||||
|
println("limit reached after "+n+" rounds")
|
||||||
|
break sum
|
||||||
|
}
|
||||||
|
else
|
||||||
|
println("%g, delta=%g"(sum, delta))
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println("limit not reached")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val limit = findSumLimit { n -> 1.0/n/n }
|
||||||
|
assert( limit != null )
|
||||||
|
println("Result: "+limit)
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user