Dev #127
@ -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 {
|
plugins { id("scientifik.mpp") }
|
||||||
id("scientifik.mpp")
|
repositories { maven("https://dl.bintray.com/hotkeytlt/maven") }
|
||||||
}
|
|
||||||
|
|
||||||
repositories{
|
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
@ -13,9 +8,22 @@ kotlin.sourceSets {
|
|||||||
implementation("com.github.h0tk3y.betterParse:better-parse-multiplatform:0.4.0-alpha-3")
|
implementation("com.github.h0tk3y.betterParse:better-parse-multiplatform:0.4.0-alpha-3")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.github.h0tk3y.betterParse:better-parse-jvm:0.4.0-alpha-3")
|
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.expressions.Expression
|
||||||
import scientifik.kmath.operations.Algebra
|
import scientifik.kmath.expressions.ExpressionAlgebra
|
||||||
import scientifik.kmath.operations.Space
|
import scientifik.kmath.operations.*
|
||||||
import scientifik.kmath.operations.invoke
|
|
||||||
import kotlin.reflect.full.memberFunctions
|
import kotlin.reflect.full.memberFunctions
|
||||||
import kotlin.reflect.jvm.jvmName
|
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)
|
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 tryEvaluate(): T = value
|
||||||
override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitLoadFromConstants(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(
|
internal abstract class FunctionalCompiledExpression<T> internal constructor(
|
||||||
@JvmField protected val algebra: Algebra<T>,
|
@JvmField protected val algebra: Algebra<T>,
|
||||||
@JvmField protected val constants: Array<Any>
|
@JvmField protected val constants: Array<Any>
|
||||||
) : Expression<T> {
|
) : Expression<T> {
|
||||||
abstract override fun invoke(arguments: Map<String, T>): 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.ClassWriter
|
||||||
import org.objectweb.asm.Label
|
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)
|
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")
|
@Suppress("PrivatePropertyName")
|
||||||
private val T_ALGEBRA_CLASS: String = algebra.javaClass.name.replace(oldChar = '.', newChar = '/')
|
private val T_ALGEBRA_CLASS: String = algebra.javaClass.name.replace(oldChar = '.', newChar = '/')
|
||||||
@ -236,7 +237,8 @@ class AsmGenerationContext<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
visitLdcInsn(name)
|
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()
|
visitCastToT()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +277,7 @@ class AsmGenerationContext<T>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal const val FUNCTIONAL_COMPILED_EXPRESSION_CLASS =
|
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 MAP_CLASS = "java/util/Map"
|
||||||
internal const val OBJECT_CLASS = "java/lang/Object"
|
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.MethodVisitor
|
||||||
import org.objectweb.asm.Opcodes.*
|
import org.objectweb.asm.Opcodes.*
|
@ -1,4 +1,4 @@
|
|||||||
package scientifik.kmath.expressions.asm
|
package scientifik.kmath.asm
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun <T> AsmExpression<T>.optimize(): AsmExpression<T> {
|
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
|
package scietifik.kmath.ast
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import scientifik.kmath.ast.evaluate
|
import scientifik.kmath.ast.evaluate
|
||||||
import scientifik.kmath.ast.parseMath
|
import scientifik.kmath.ast.parseMath
|
||||||
import scientifik.kmath.operations.Complex
|
import scientifik.kmath.operations.Complex
|
||||||
import scientifik.kmath.operations.ComplexField
|
import scientifik.kmath.operations.ComplexField
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class ParserTest {
|
internal class ParserTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,30 +1,23 @@
|
|||||||
package scientifik.kmath.expressions
|
package scientifik.kmath.expressions
|
||||||
|
|
||||||
import scientifik.kmath.operations.Algebra
|
|
||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.Ring
|
import scientifik.kmath.operations.Ring
|
||||||
import scientifik.kmath.operations.Space
|
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]
|
* 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)
|
FunctionalExpressionSpace(this).run(block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a functional expression on this [Ring]
|
* 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)
|
FunctionalExpressionRing(this).run(block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a functional expression on this [Field]
|
* 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)
|
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
|
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> {
|
Expression<T> {
|
||||||
override fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
|
override fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class FunctionalExpressionAlgebra<T>(val algebra: Algebra<T>) :
|
interface FunctionalExpressionAlgebra<T, A : Algebra<T>> : ExpressionAlgebra<T, Expression<T>> {
|
||||||
Algebra<Expression<T>>,
|
val algebra: A
|
||||||
ExpressionAlgebra<T, Expression<T>> {
|
|
||||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
|
||||||
FunctionalUnaryOperation(algebra, operation, arg)
|
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
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 const(value: T): Expression<T> = FunctionalConstantExpression(value)
|
||||||
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
|
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class FunctionalExpressionSpace<T>(val space: Space<T>) :
|
open class FunctionalExpressionSpace<T, A>(override val algebra: A) : FunctionalExpressionAlgebra<T, A>,
|
||||||
FunctionalExpressionAlgebra<T>(space),
|
Space<Expression<T>> where A : Space<T> {
|
||||||
Space<Expression<T>> {
|
override val zero: Expression<T>
|
||||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
get() = const(algebra.zero)
|
||||||
FunctionalUnaryOperation(algebra, operation, arg)
|
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
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> =
|
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>.plus(arg: T): Expression<T> = this + const(arg)
|
||||||
operator fun Expression<T>.minus(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.plus(arg: Expression<T>): Expression<T> = arg + this
|
||||||
operator fun T.minus(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>
|
override val one: Expression<T>
|
||||||
get() = const(this.ring.one)
|
get() = const(algebra.one)
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||||
FunctionalUnaryOperation(algebra, operation, arg)
|
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> =
|
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
||||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
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> =
|
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 Expression<T>.times(arg: T): Expression<T> = this * const(arg)
|
||||||
operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
||||||
}
|
}
|
||||||
|
|
||||||
open class FunctionalExpressionField<T>(val field: Field<T>) :
|
open class FunctionalExpressionField<T, A>(override val algebra: A) :
|
||||||
FunctionalExpressionRing<T>(field),
|
FunctionalExpressionRing<T, A>(algebra),
|
||||||
Field<Expression<T>> {
|
Field<Expression<T>> where A : Field<T>, A : NumericAlgebra<T> {
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
||||||
FunctionalUnaryOperation(algebra, operation, arg)
|
FunctionalUnaryOperation(algebra, operation, arg)
|
||||||
@ -95,7 +102,7 @@ open class FunctionalExpressionField<T>(val field: Field<T>) :
|
|||||||
FunctionalBinaryOperation(algebra, operation, left, right)
|
FunctionalBinaryOperation(algebra, operation, left, right)
|
||||||
|
|
||||||
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
|
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 Expression<T>.div(arg: T): Expression<T> = this / const(arg)
|
||||||
operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
||||||
|
@ -45,6 +45,5 @@ include(
|
|||||||
":kmath-for-real",
|
":kmath-for-real",
|
||||||
":kmath-geometry",
|
":kmath-geometry",
|
||||||
":kmath-ast",
|
":kmath-ast",
|
||||||
":kmath-asm",
|
|
||||||
":examples"
|
":examples"
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user