Provide dynamic operations currying for Algebra<T> instead of eager calls and add JS code generation support #162

Merged
CommanderTvis merged 44 commits from feature/dynamic-ops-currying into dev 2021-01-05 16:36:51 +03:00
7 changed files with 73 additions and 69 deletions
Showing only changes of commit 1a5efd0a17 - Show all commits

View File

@ -1,18 +1,18 @@
package kscience.kmath.estree package kscience.kmath.estree
import kscience.kmath.ast.mstInField import kscience.kmath.ast.*
import kscience.kmath.ast.mstInRing
import kscience.kmath.ast.mstInSpace
import kscience.kmath.expressions.invoke import kscience.kmath.expressions.invoke
import kscience.kmath.operations.ByteRing import kscience.kmath.operations.ByteRing
import kscience.kmath.operations.ComplexField
import kscience.kmath.operations.RealField import kscience.kmath.operations.RealField
import kscience.kmath.operations.toComplex
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestESTreeAlgebras { internal class TestESTreeConsistencyWithInterpreter {
@Test @Test
fun space() { fun mstSpace() {
val res1 = ByteRing.mstInSpace { val res1 = MstSpace.mstInSpace {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (multiply(
@ -23,9 +23,9 @@ internal class TestESTreeAlgebras {
number(1) number(1)
) + symbol("x") + zero ) + symbol("x") + zero
}("x" to 2.toByte()) }("x" to MST.Numeric(2))
val res2 = ByteRing.mstInSpace { val res2 = MstSpace.mstInSpace {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (multiply(
@ -36,13 +36,13 @@ internal class TestESTreeAlgebras {
number(1) number(1)
) + symbol("x") + zero ) + symbol("x") + zero
}.compile()("x" to 2.toByte()) }.compile()("x" to MST.Numeric(2))
assertEquals(res1, res2) assertEquals(res1, res2)
} }
@Test @Test
fun ring() { fun byteRing() {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
@ -72,7 +72,7 @@ internal class TestESTreeAlgebras {
} }
@Test @Test
fun field() { fun realField() {
val res1 = RealField.mstInField { val res1 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
@ -91,4 +91,25 @@ internal class TestESTreeAlgebras {
assertEquals(res1, res2) assertEquals(res1, res2)
} }
@Test
fun complexField() {
val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+ number(1),
number(1) / 2 + number(2.0) * one
) + zero
}("x" to 2.0.toComplex())
val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+ number(1),
number(1) / 2 + number(2.0) * one
) + zero
}.compile()("x" to 2.0.toComplex())
assertEquals(res1, res2)
}
} }

View File

@ -3,17 +3,13 @@ package kscience.kmath.estree
import kscience.kmath.ast.mstInExtendedField import kscience.kmath.ast.mstInExtendedField
import kscience.kmath.ast.mstInField import kscience.kmath.ast.mstInField
import kscience.kmath.ast.mstInSpace import kscience.kmath.ast.mstInSpace
import kscience.kmath.expressions.Expression
import kscience.kmath.expressions.StringSymbol
import kscience.kmath.expressions.invoke import kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField import kscience.kmath.operations.RealField
import kotlin.math.pow
import kotlin.random.Random import kotlin.random.Random
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.time.measureTime
internal class TestESTreeExpressions { internal class TestESTreeOperationsSupport {
@Test @Test
fun testUnaryOperationInvocation() { fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") }.compile() val expression = RealField.mstInSpace { -symbol("x") }.compile()
@ -36,21 +32,10 @@ internal class TestESTreeExpressions {
@Test @Test
fun testMultipleCalls() { fun testMultipleCalls() {
val e1 = val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile()
RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile() val r = Random(0)
val e2 = Expression<Double> { a ->
val x = a.getValue(StringSymbol("x"))
kotlin.math.sin(x).pow(4) - 6 * x / kotlin.math.tanh(x)
}
var r = Random(0)
var s = 0.0 var s = 0.0
measureTime { repeat(1000000) { s += e1("x" to r.nextDouble()) } }.also(::println) repeat(1000000) { s += e("x" to r.nextDouble()) }
println(s)
s = 0.0
r = Random(0)
measureTime { repeat(1000000) { s += e2("x" to r.nextDouble()) } }.also(::println)
println(s) println(s)
} }
} }

View File

@ -9,13 +9,13 @@ import kotlin.test.assertFailsWith
internal class TestESTreeVariables { internal class TestESTreeVariables {
@Test @Test
fun testVariableWithoutDefault() { fun testVariable() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { symbol("x") }.compile()
assertEquals(1.toByte(), expr("x" to 1.toByte())) assertEquals(1.toByte(), expr("x" to 1.toByte()))
} }
@Test @Test
fun testVariableWithoutDefaultFails() { fun testUndefinedVariableFails() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { symbol("x") }.compile()
assertFailsWith<NoSuchElementException> { expr() } assertFailsWith<NoSuchElementException> { expr() }
} }

View File

@ -1,18 +1,18 @@
package kscience.kmath.asm package kscience.kmath.asm
import kscience.kmath.ast.mstInField import kscience.kmath.ast.*
import kscience.kmath.ast.mstInRing
import kscience.kmath.ast.mstInSpace
import kscience.kmath.expressions.invoke import kscience.kmath.expressions.invoke
import kscience.kmath.operations.ByteRing import kscience.kmath.operations.ByteRing
import kscience.kmath.operations.ComplexField
import kscience.kmath.operations.RealField import kscience.kmath.operations.RealField
import kscience.kmath.operations.toComplex
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestAsmAlgebras { internal class TestAsmConsistencyWithInterpreter {
@Test @Test
fun space() { fun mstSpace() {
val res1 = ByteRing.mstInSpace { val res1 = MstSpace.mstInSpace {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (multiply(
@ -23,9 +23,9 @@ internal class TestAsmAlgebras {
number(1) number(1)
) + symbol("x") + zero ) + symbol("x") + zero
}("x" to 2.toByte()) }("x" to MST.Numeric(2))
val res2 = ByteRing.mstInSpace { val res2 = MstSpace.mstInSpace {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (multiply(
@ -36,13 +36,13 @@ internal class TestAsmAlgebras {
number(1) number(1)
) + symbol("x") + zero ) + symbol("x") + zero
}.compile()("x" to 2.toByte()) }.compile()("x" to MST.Numeric(2))
assertEquals(res1, res2) assertEquals(res1, res2)
} }
@Test @Test
fun ring() { fun byteRing() {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperation("+")( binaryOperation("+")(
unaryOperation("+")( unaryOperation("+")(
@ -72,7 +72,7 @@ internal class TestAsmAlgebras {
} }
@Test @Test
fun field() { fun realField() {
val res1 = RealField.mstInField { val res1 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
@ -91,4 +91,25 @@ internal class TestAsmAlgebras {
assertEquals(res1, res2) assertEquals(res1, res2)
} }
@Test
fun complexField() {
val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+ number(1),
number(1) / 2 + number(2.0) * one
) + zero
}("x" to 2.0.toComplex())
val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
+ number(1),
number(1) / 2 + number(2.0) * one
) + zero
}.compile()("x" to 2.0.toComplex())
assertEquals(res1, res2)
}
} }

View File

@ -9,7 +9,7 @@ import kotlin.random.Random
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestAsmExpressions { internal class TestAsmOperationsSupport {
@Test @Test
fun testUnaryOperationInvocation() { fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") }.compile() val expression = RealField.mstInSpace { -symbol("x") }.compile()

View File

@ -9,13 +9,13 @@ import kotlin.test.assertFailsWith
internal class TestAsmVariables { internal class TestAsmVariables {
@Test @Test
fun testVariableWithoutDefault() { fun testVariable() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { symbol("x") }.compile()
assertEquals(1.toByte(), expr("x" to 1.toByte())) assertEquals(1.toByte(), expr("x" to 1.toByte()))
} }
@Test @Test
fun testVariableWithoutDefaultFails() { fun testUndefinedVariableFails() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { symbol("x") }.compile()
assertFailsWith<NoSuchElementException> { expr() } assertFailsWith<NoSuchElementException> { expr() }
} }

View File

@ -1,23 +0,0 @@
package kscience.kmath.ast
import kscience.kmath.asm.compile
import kscience.kmath.asm.expression
import kscience.kmath.expressions.invoke
import kscience.kmath.operations.Complex
import kscience.kmath.operations.ComplexField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class AsmTest {
@Test
fun `compile MST`() {
val res = ComplexField.expression("2+2*(2+2)".parseMath())()
assertEquals(Complex(10.0, 0.0), res)
}
@Test
fun `compile MSTExpression`() {
val res = ComplexField.mstInField { number(2) + number(2) * (number(2) + number(2)) }.compile()()
assertEquals(Complex(10.0, 0.0), res)
}
}