Merge kmath-asm and kmath-ast modules, make all the ExpressionAlgebras concise and consistent, implement new-styled builders both for ASM and F. expressions
This commit is contained in:
parent
b902f3980a
commit
3ec1f7b5f1
@ -1,10 +0,0 @@
|
||||
plugins {
|
||||
id("scientifik.jvm")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(path = ":kmath-core"))
|
||||
implementation("org.ow2.asm:asm:8.0.1")
|
||||
implementation("org.ow2.asm:asm-commons:8.0.1")
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
|
||||
import scientifik.kmath.expressions.ExpressionAlgebra
|
||||
import scientifik.kmath.operations.*
|
||||
|
||||
open class AsmExpressionAlgebra<T>(val algebra: Algebra<T>) :
|
||||
Algebra<AsmExpression<T>>,
|
||||
ExpressionAlgebra<T, AsmExpression<T>> {
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun const(value: T): AsmExpression<T> = AsmConstantExpression(value)
|
||||
override fun variable(name: String, default: T?): AsmExpression<T> = AsmVariableExpression(name, default)
|
||||
}
|
||||
|
||||
open class AsmExpressionSpace<T>(
|
||||
val space: Space<T>
|
||||
) : AsmExpressionAlgebra<T>(space), Space<AsmExpression<T>> {
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override val zero: AsmExpression<T> = AsmConstantExpression(space.zero)
|
||||
|
||||
override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(space, SpaceOperations.PLUS_OPERATION, a, b)
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> = AsmConstProductExpression(space, a, k)
|
||||
operator fun AsmExpression<T>.plus(arg: T): AsmExpression<T> = this + const(arg)
|
||||
operator fun AsmExpression<T>.minus(arg: T): AsmExpression<T> = this - const(arg)
|
||||
operator fun T.plus(arg: AsmExpression<T>): AsmExpression<T> = arg + this
|
||||
operator fun T.minus(arg: AsmExpression<T>): AsmExpression<T> = arg - this
|
||||
}
|
||||
|
||||
open class AsmExpressionRing<T>(private val ring: Ring<T>) : AsmExpressionSpace<T>(ring), Ring<AsmExpression<T>> {
|
||||
override val one: AsmExpression<T>
|
||||
get() = const(this.ring.one)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun number(value: Number): AsmExpression<T> = const(ring { one * value })
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(space, RingOperations.TIMES_OPERATION, a, b)
|
||||
|
||||
operator fun AsmExpression<T>.times(arg: T): AsmExpression<T> = this * const(arg)
|
||||
operator fun T.times(arg: AsmExpression<T>): AsmExpression<T> = arg * this
|
||||
}
|
||||
|
||||
open class AsmExpressionField<T>(private val field: Field<T>) :
|
||||
AsmExpressionRing<T>(field),
|
||||
Field<AsmExpression<T>> {
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun divide(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(field, FieldOperations.DIV_OPERATION, a, b)
|
||||
|
||||
operator fun AsmExpression<T>.div(arg: T): AsmExpression<T> = this / const(arg)
|
||||
operator fun T.div(arg: AsmExpression<T>): AsmExpression<T> = arg / this
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.expressions.ExpressionAlgebra
|
||||
import scientifik.kmath.operations.*
|
||||
|
||||
@PublishedApi
|
||||
internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String {
|
||||
val name = "scientifik.kmath.expressions.generated.AsmCompiledExpression_${expression.hashCode()}_$collision"
|
||||
|
||||
try {
|
||||
Class.forName(name)
|
||||
} catch (ignored: ClassNotFoundException) {
|
||||
return name
|
||||
}
|
||||
|
||||
return buildName(expression, collision + 1)
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified T, E : ExpressionAlgebra<T, AsmExpression<T>>> asm(
|
||||
i: E,
|
||||
algebra: Algebra<T>,
|
||||
block: E.() -> AsmExpression<T>
|
||||
): Expression<T> {
|
||||
val expression = i.block().optimize()
|
||||
val ctx = AsmGenerationContext(T::class.java, algebra, buildName(expression))
|
||||
expression.invoke(ctx)
|
||||
return ctx.generate()
|
||||
}
|
||||
|
||||
inline fun <reified T> buildAsmAlgebra(
|
||||
algebra: Algebra<T>,
|
||||
block: AsmExpressionAlgebra<T>.() -> AsmExpression<T>
|
||||
): Expression<T> = asm(AsmExpressionAlgebra(algebra), algebra, block)
|
||||
|
||||
inline fun <reified T> buildAsmSpace(
|
||||
algebra: Space<T>,
|
||||
block: AsmExpressionSpace<T>.() -> AsmExpression<T>
|
||||
): Expression<T> = asm(AsmExpressionSpace(algebra), algebra, block)
|
||||
|
||||
inline fun <reified T> buildAsmRing(
|
||||
algebra: Ring<T>,
|
||||
block: AsmExpressionRing<T>.() -> AsmExpression<T>
|
||||
): Expression<T> = asm(AsmExpressionRing(algebra), algebra, block)
|
||||
|
||||
inline fun <reified T> buildAsmField(
|
||||
algebra: Field<T>,
|
||||
block: AsmExpressionField<T>.() -> AsmExpression<T>
|
||||
): Expression<T> = asm(AsmExpressionField(algebra), algebra, block)
|
@ -1,43 +0,0 @@
|
||||
package scientifik.kmath.expressions
|
||||
|
||||
import scientifik.kmath.expressions.asm.AsmExpression
|
||||
import scientifik.kmath.expressions.asm.AsmExpressionField
|
||||
import scientifik.kmath.expressions.asm.buildAsmField
|
||||
import scientifik.kmath.operations.RealField
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class AsmTest {
|
||||
private fun testDoubleExpression(
|
||||
expected: Double?,
|
||||
arguments: Map<String, Double> = emptyMap(),
|
||||
block: AsmExpressionField<Double>.() -> AsmExpression<Double>
|
||||
): Unit = assertEquals(expected = expected, actual = buildAsmField(RealField, block)(arguments))
|
||||
|
||||
@Test
|
||||
fun testConstantsSum(): Unit = testDoubleExpression(16.0) { const(8.0) + 8.0 }
|
||||
|
||||
@Test
|
||||
fun testVarsSum(): Unit = testDoubleExpression(1000.0, mapOf("x" to 500.0)) { variable("x") + 500.0 }
|
||||
|
||||
@Test
|
||||
fun testProduct(): Unit = testDoubleExpression(24.0) { const(4.0) * const(6.0) }
|
||||
|
||||
@Test
|
||||
fun testConstantProduct(): Unit = testDoubleExpression(984.0) { const(8.0) * 123 }
|
||||
|
||||
@Test
|
||||
fun testVarsConstantProductVar(): Unit = testDoubleExpression(984.0, mapOf("x" to 8.0)) { variable("x") * 123 }
|
||||
|
||||
@Test
|
||||
fun testSubtraction(): Unit = testDoubleExpression(2.0) { const(4.0) - 2.0 }
|
||||
|
||||
@Test
|
||||
fun testDivision(): Unit = testDoubleExpression(64.0) { const(128.0) / 2 }
|
||||
|
||||
@Test
|
||||
fun testDirectUnaryCall(): Unit = testDoubleExpression(64.0) { unaryOperation("+", const(64.0)) }
|
||||
|
||||
@Test
|
||||
fun testDirectBinaryCall(): Unit = testDoubleExpression(4096.0) { binaryOperation("*", const(64.0), const(64.0)) }
|
||||
}
|
@ -1,10 +1,5 @@
|
||||
plugins {
|
||||
id("scientifik.mpp")
|
||||
}
|
||||
|
||||
repositories{
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
}
|
||||
plugins { id("scientifik.mpp") }
|
||||
repositories { maven("https://dl.bintray.com/hotkeytlt/maven") }
|
||||
|
||||
kotlin.sourceSets {
|
||||
commonMain {
|
||||
@ -13,9 +8,22 @@ kotlin.sourceSets {
|
||||
implementation("com.github.h0tk3y.betterParse:better-parse-multiplatform:0.4.0-alpha-3")
|
||||
}
|
||||
}
|
||||
|
||||
jvmMain {
|
||||
dependencies {
|
||||
implementation("com.github.h0tk3y.betterParse:better-parse-jvm:0.4.0-alpha-3")
|
||||
implementation("org.ow2.asm:asm:8.0.1")
|
||||
implementation("org.ow2.asm:asm-commons:8.0.1")
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
}
|
||||
|
||||
jvmTest {
|
||||
dependencies {
|
||||
implementation(kotlin("test"))
|
||||
implementation(kotlin("test-junit5"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> { useJUnitPlatform() }
|
||||
|
@ -1,9 +1,8 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
package scientifik.kmath.asm
|
||||
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.operations.Space
|
||||
import scientifik.kmath.operations.invoke
|
||||
import scientifik.kmath.expressions.ExpressionAlgebra
|
||||
import scientifik.kmath.operations.*
|
||||
import kotlin.reflect.full.memberFunctions
|
||||
import kotlin.reflect.jvm.jvmName
|
||||
|
||||
@ -109,11 +108,13 @@ internal class AsmBinaryOperation<T>(
|
||||
}
|
||||
}
|
||||
|
||||
internal class AsmVariableExpression<T>(private val name: String, private val default: T? = null) : AsmExpression<T> {
|
||||
internal class AsmVariableExpression<T>(private val name: String, private val default: T? = null) :
|
||||
AsmExpression<T> {
|
||||
override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitLoadFromVariables(name, default)
|
||||
}
|
||||
|
||||
internal class AsmConstantExpression<T>(private val value: T) : AsmExpression<T> {
|
||||
internal class AsmConstantExpression<T>(private val value: T) :
|
||||
AsmExpression<T> {
|
||||
override fun tryEvaluate(): T = value
|
||||
override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitLoadFromConstants(value)
|
||||
}
|
||||
@ -141,9 +142,88 @@ internal class AsmConstProductExpression<T>(
|
||||
}
|
||||
}
|
||||
|
||||
internal class AsmNumberExpression<T>(private val context: NumericAlgebra<T>, private val value: Number) : AsmExpression<T> {
|
||||
override fun tryEvaluate(): T? = context.number(value)
|
||||
|
||||
override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitNumberConstant(value)
|
||||
}
|
||||
|
||||
internal abstract class FunctionalCompiledExpression<T> internal constructor(
|
||||
@JvmField protected val algebra: Algebra<T>,
|
||||
@JvmField protected val constants: Array<Any>
|
||||
) : Expression<T> {
|
||||
abstract override fun invoke(arguments: Map<String, T>): T
|
||||
}
|
||||
|
||||
interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmExpression<T>>,
|
||||
ExpressionAlgebra<T, AsmExpression<T>> {
|
||||
val algebra: A
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun number(value: Number): AsmExpression<T> = AsmNumberExpression(algebra, value)
|
||||
override fun const(value: T): AsmExpression<T> = AsmConstantExpression(value)
|
||||
override fun variable(name: String, default: T?): AsmExpression<T> = AsmVariableExpression(name, default)
|
||||
}
|
||||
|
||||
open class AsmExpressionSpace<T, A>(override val algebra: A) : AsmExpressionAlgebra<T, A>,
|
||||
Space<AsmExpression<T>> where A : Space<T>, A : NumericAlgebra<T> {
|
||||
override val zero: AsmExpression<T>
|
||||
get() = const(algebra.zero)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> = AsmConstProductExpression(algebra, a, k)
|
||||
operator fun AsmExpression<T>.plus(arg: T): AsmExpression<T> = this + const(arg)
|
||||
operator fun AsmExpression<T>.minus(arg: T): AsmExpression<T> = this - const(arg)
|
||||
operator fun T.plus(arg: AsmExpression<T>): AsmExpression<T> = arg + this
|
||||
operator fun T.minus(arg: AsmExpression<T>): AsmExpression<T> = arg - this
|
||||
}
|
||||
|
||||
open class AsmExpressionRing<T, A>(override val algebra: A) : AsmExpressionSpace<T, A>(algebra),
|
||||
Ring<AsmExpression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
|
||||
override val one: AsmExpression<T>
|
||||
get() = const(algebra.one)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun number(value: Number): AsmExpression<T> = const(algebra { one * value })
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b)
|
||||
|
||||
operator fun AsmExpression<T>.times(arg: T): AsmExpression<T> = this * const(arg)
|
||||
operator fun T.times(arg: AsmExpression<T>): AsmExpression<T> = arg * this
|
||||
}
|
||||
|
||||
open class AsmExpressionField<T, A>(override val algebra: A) :
|
||||
AsmExpressionRing<T, A>(algebra),
|
||||
Field<AsmExpression<T>> where A : Field<T>, A : NumericAlgebra<T> {
|
||||
|
||||
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun divide(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b)
|
||||
|
||||
operator fun AsmExpression<T>.div(arg: T): AsmExpression<T> = this / const(arg)
|
||||
operator fun T.div(arg: AsmExpression<T>): AsmExpression<T> = arg / this
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
package scientifik.kmath.asm
|
||||
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import org.objectweb.asm.Label
|
||||
@ -15,7 +15,8 @@ class AsmGenerationContext<T>(
|
||||
internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size)
|
||||
}
|
||||
|
||||
private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
|
||||
private val classLoader: ClassLoader =
|
||||
ClassLoader(javaClass.classLoader)
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val T_ALGEBRA_CLASS: String = algebra.javaClass.name.replace(oldChar = '.', newChar = '/')
|
||||
@ -236,7 +237,8 @@ class AsmGenerationContext<T>(
|
||||
}
|
||||
|
||||
visitLdcInsn(name)
|
||||
visitMethodInsn(Opcodes.INVOKEINTERFACE, MAP_CLASS, "get", "(L$OBJECT_CLASS;)L$OBJECT_CLASS;", true)
|
||||
visitMethodInsn(Opcodes.INVOKEINTERFACE,
|
||||
MAP_CLASS, "get", "(L$OBJECT_CLASS;)L$OBJECT_CLASS;", true)
|
||||
visitCastToT()
|
||||
}
|
||||
|
||||
@ -275,7 +277,7 @@ class AsmGenerationContext<T>(
|
||||
)
|
||||
|
||||
internal const val FUNCTIONAL_COMPILED_EXPRESSION_CLASS =
|
||||
"scientifik/kmath/expressions/asm/FunctionalCompiledExpression"
|
||||
"scientifik/kmath/asm/FunctionalCompiledExpression"
|
||||
|
||||
internal const val MAP_CLASS = "java/util/Map"
|
||||
internal const val OBJECT_CLASS = "java/lang/Object"
|
@ -0,0 +1,53 @@
|
||||
package scientifik.kmath.asm
|
||||
|
||||
import scientifik.kmath.ast.MST
|
||||
import scientifik.kmath.ast.evaluate
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.operations.*
|
||||
|
||||
@PublishedApi
|
||||
internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String {
|
||||
val name = "scientifik.kmath.expressions.generated.AsmCompiledExpression_${expression.hashCode()}_$collision"
|
||||
|
||||
try {
|
||||
Class.forName(name)
|
||||
} catch (ignored: ClassNotFoundException) {
|
||||
return name
|
||||
}
|
||||
|
||||
return buildName(expression, collision + 1)
|
||||
}
|
||||
|
||||
inline fun <reified T> AsmExpression<T>.compile(algebra: Algebra<T>): Expression<T> {
|
||||
val ctx = AsmGenerationContext(T::class.java, algebra, buildName(this))
|
||||
invoke(ctx)
|
||||
return ctx.generate()
|
||||
}
|
||||
|
||||
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
||||
expressionAlgebra: E,
|
||||
block: E.() -> AsmExpression<T>
|
||||
): Expression<T> = expressionAlgebra.block().compile(expressionAlgebra.algebra)
|
||||
|
||||
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
||||
expressionAlgebra: E,
|
||||
ast: MST
|
||||
): Expression<T> = asm(expressionAlgebra) { evaluate(ast) }
|
||||
|
||||
inline fun <reified T, A> A.asmSpace(block: AsmExpressionSpace<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
||||
AsmExpressionSpace(this).let { it.block().compile(it.algebra) }
|
||||
|
||||
inline fun <reified T, A> A.asmSpace(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
||||
asmSpace { evaluate(ast) }
|
||||
|
||||
inline fun <reified T, A> A.asmRing(block: AsmExpressionRing<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
||||
AsmExpressionRing(this).let { it.block().compile(it.algebra) }
|
||||
|
||||
inline fun <reified T, A> A.asmRing(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
||||
asmRing { evaluate(ast) }
|
||||
|
||||
inline fun <reified T, A> A.asmField(block: AsmExpressionField<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
||||
AsmExpressionField(this).let { it.block().compile(it.algebra) }
|
||||
|
||||
inline fun <reified T, A> A.asmField(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
||||
asmRing { evaluate(ast) }
|
@ -1,4 +1,4 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
package scientifik.kmath.asm
|
||||
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Opcodes.*
|
@ -1,4 +1,4 @@
|
||||
package scientifik.kmath.expressions.asm
|
||||
package scientifik.kmath.asm
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T> AsmExpression<T>.optimize(): AsmExpression<T> {
|
@ -1,23 +0,0 @@
|
||||
package scientifik.kmath.ast
|
||||
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.operations.NumericAlgebra
|
||||
|
||||
//TODO stubs for asm generation
|
||||
|
||||
interface AsmExpression<T>
|
||||
|
||||
interface AsmExpressionAlgebra<T, A : Algebra<T>> : NumericAlgebra<AsmExpression<T>> {
|
||||
val algebra: A
|
||||
}
|
||||
|
||||
fun <T> AsmExpression<T>.compile(): Expression<T> = TODO()
|
||||
|
||||
//TODO add converter for functional expressions
|
||||
|
||||
inline fun <reified T : Any, A : Algebra<T>> A.asm(
|
||||
block: AsmExpressionAlgebra<T, A>.() -> AsmExpression<T>
|
||||
): Expression<T> = TODO()
|
||||
|
||||
inline fun <reified T : Any, A : Algebra<T>> A.asm(ast: MST): Expression<T> = asm { evaluate(ast) }
|
18
kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt
Normal file
18
kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package scietifik.kmath.ast
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import scientifik.kmath.asm.asmField
|
||||
import scientifik.kmath.ast.parseMath
|
||||
import scientifik.kmath.expressions.invoke
|
||||
import scientifik.kmath.operations.Complex
|
||||
import scientifik.kmath.operations.ComplexField
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class AsmTest {
|
||||
@Test
|
||||
fun parsedExpression() {
|
||||
val mst = "2+2*(2+2)".parseMath()
|
||||
val res = ComplexField.asmField(mst)()
|
||||
assertEquals(Complex(10.0, 0.0), res)
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package scietifik.kmath.ast
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import scientifik.kmath.ast.evaluate
|
||||
import scientifik.kmath.ast.parseMath
|
||||
import scientifik.kmath.operations.Complex
|
||||
import scientifik.kmath.operations.ComplexField
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ParserTest {
|
||||
@Test
|
||||
|
@ -1,30 +1,23 @@
|
||||
package scientifik.kmath.expressions
|
||||
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.operations.Field
|
||||
import scientifik.kmath.operations.Ring
|
||||
import scientifik.kmath.operations.Space
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Algebra]
|
||||
*/
|
||||
fun <T> Algebra<T>.buildExpression(block: FunctionalExpressionAlgebra<T>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionAlgebra(this).run(block)
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Space]
|
||||
*/
|
||||
fun <T> Space<T>.buildExpression(block: FunctionalExpressionSpace<T>.() -> Expression<T>): Expression<T> =
|
||||
fun <T> Space<T>.buildExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionSpace(this).run(block)
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Ring]
|
||||
*/
|
||||
fun <T> Ring<T>.buildExpression(block: FunctionalExpressionRing<T>.() -> Expression<T>): Expression<T> =
|
||||
fun <T> Ring<T>.buildExpression(block: FunctionalExpressionRing<T, Ring<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionRing(this).run(block)
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Field]
|
||||
*/
|
||||
fun <T> Field<T>.buildExpression(block: FunctionalExpressionField<T>.() -> Expression<T>): Expression<T> =
|
||||
fun <T> Field<T>.buildExpression(block: FunctionalExpressionField<T, Field<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionField(this).run(block)
|
||||
|
@ -26,48 +26,55 @@ internal class FunctionalConstantExpression<T>(val value: T) : Expression<T> {
|
||||
override fun invoke(arguments: Map<String, T>): T = value
|
||||
}
|
||||
|
||||
internal class FunctionalConstProductExpression<T>(val context: Space<T>, val expr: Expression<T>, val const: Number) :
|
||||
internal class FunctionalConstProductExpression<T>(
|
||||
val context: Space<T>,
|
||||
val expr: Expression<T>,
|
||||
val const: Number
|
||||
) :
|
||||
Expression<T> {
|
||||
override fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
|
||||
}
|
||||
|
||||
open class FunctionalExpressionAlgebra<T>(val algebra: Algebra<T>) :
|
||||
Algebra<Expression<T>>,
|
||||
ExpressionAlgebra<T, Expression<T>> {
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
interface FunctionalExpressionAlgebra<T, A : Algebra<T>> : ExpressionAlgebra<T, Expression<T>> {
|
||||
val algebra: A
|
||||
|
||||
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun const(value: T): Expression<T> = FunctionalConstantExpression(value)
|
||||
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
|
||||
}
|
||||
|
||||
open class FunctionalExpressionSpace<T>(val space: Space<T>) :
|
||||
FunctionalExpressionAlgebra<T>(space),
|
||||
Space<Expression<T>> {
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
open class FunctionalExpressionSpace<T, A>(override val algebra: A) : FunctionalExpressionAlgebra<T, A>,
|
||||
Space<Expression<T>> where A : Space<T> {
|
||||
override val zero: Expression<T>
|
||||
get() = const(algebra.zero)
|
||||
|
||||
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override val zero: Expression<T> = FunctionalConstantExpression(space.zero)
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
|
||||
override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(space, SpaceOperations.PLUS_OPERATION, a, b)
|
||||
FunctionalBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
|
||||
|
||||
override fun multiply(a: Expression<T>, k: Number): Expression<T> =
|
||||
FunctionalConstProductExpression(algebra, a, k)
|
||||
|
||||
override fun multiply(a: Expression<T>, k: Number): Expression<T> = FunctionalConstProductExpression(space, a, k)
|
||||
operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
|
||||
operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
|
||||
operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
|
||||
operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
|
||||
}
|
||||
|
||||
open class FunctionalExpressionRing<T>(val ring: Ring<T>) : FunctionalExpressionSpace<T>(ring), Ring<Expression<T>> {
|
||||
open class FunctionalExpressionRing<T, A>(override val algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
|
||||
Ring<Expression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
|
||||
override val one: Expression<T>
|
||||
get() = const(this.ring.one)
|
||||
get() = const(algebra.one)
|
||||
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
@ -75,18 +82,18 @@ open class FunctionalExpressionRing<T>(val ring: Ring<T>) : FunctionalExpression
|
||||
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun number(value: Number): Expression<T> = const(ring { one * value })
|
||||
override fun number(value: Number): Expression<T> = const(algebra { one * value })
|
||||
|
||||
override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(space, RingOperations.TIMES_OPERATION, a, b)
|
||||
FunctionalBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b)
|
||||
|
||||
operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
|
||||
operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
||||
}
|
||||
|
||||
open class FunctionalExpressionField<T>(val field: Field<T>) :
|
||||
FunctionalExpressionRing<T>(field),
|
||||
Field<Expression<T>> {
|
||||
open class FunctionalExpressionField<T, A>(override val algebra: A) :
|
||||
FunctionalExpressionRing<T, A>(algebra),
|
||||
Field<Expression<T>> where A : Field<T>, A : NumericAlgebra<T> {
|
||||
|
||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||
FunctionalUnaryOperation(algebra, operation, arg)
|
||||
@ -95,7 +102,7 @@ open class FunctionalExpressionField<T>(val field: Field<T>) :
|
||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
||||
|
||||
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||
FunctionalBinaryOperation(space, FieldOperations.DIV_OPERATION, a, b)
|
||||
FunctionalBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b)
|
||||
|
||||
operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
|
||||
operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
||||
|
@ -45,6 +45,5 @@ include(
|
||||
":kmath-for-real",
|
||||
":kmath-geometry",
|
||||
":kmath-ast",
|
||||
":kmath-asm",
|
||||
":examples"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user