From 3ec1f7b5f15ada3527902c448f0e9517213a4354 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 13 Jun 2020 02:26:12 +0700 Subject: [PATCH] Merge kmath-asm and kmath-ast modules, make all the ExpressionAlgebras concise and consistent, implement new-styled builders both for ASM and F. expressions --- kmath-asm/build.gradle.kts | 10 -- .../expressions/asm/AsmExpressionSpaces.kt | 74 --------------- .../kmath/expressions/asm/Builders.kt | 50 ---------- .../scientifik/kmath/expressions/AsmTest.kt | 43 --------- kmath-ast/build.gradle.kts | 28 ++++-- .../scientifik/kmath}/asm/AsmExpressions.kt | 92 +++++++++++++++++-- .../kmath}/asm/AsmGenerationContext.kt | 10 +- .../kotlin/scientifik/kmath/asm/Builders.kt | 53 +++++++++++ .../scientifik/kmath}/asm/MethodVisitors.kt | 2 +- .../scientifik/kmath}/asm/Optimization.kt | 2 +- .../kmath/ast/{parser.kt => Parser.kt} | 0 .../kotlin/scientifik/kmath/ast/asm.kt | 23 ----- .../kotlin/scietifik/kmath/ast/AsmTest.kt | 18 ++++ .../kotlin/scietifik/kmath/ast/ParserTest.kt | 10 +- .../scientifik/kmath/expressions/Builders.kt | 13 +-- .../expressions/FunctionalExpressions.kt | 51 +++++----- settings.gradle.kts | 1 - 17 files changed, 220 insertions(+), 260 deletions(-) delete mode 100644 kmath-asm/build.gradle.kts delete mode 100644 kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressionSpaces.kt delete mode 100644 kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Builders.kt delete mode 100644 kmath-asm/src/test/kotlin/scientifik/kmath/expressions/AsmTest.kt rename {kmath-asm/src/main/kotlin/scientifik/kmath/expressions => kmath-ast/src/jvmMain/kotlin/scientifik/kmath}/asm/AsmExpressions.kt (52%) rename {kmath-asm/src/main/kotlin/scientifik/kmath/expressions => kmath-ast/src/jvmMain/kotlin/scientifik/kmath}/asm/AsmGenerationContext.kt (96%) create mode 100644 kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt rename {kmath-asm/src/main/kotlin/scientifik/kmath/expressions => kmath-ast/src/jvmMain/kotlin/scientifik/kmath}/asm/MethodVisitors.kt (94%) rename {kmath-asm/src/main/kotlin/scientifik/kmath/expressions => kmath-ast/src/jvmMain/kotlin/scientifik/kmath}/asm/Optimization.kt (80%) rename kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/{parser.kt => Parser.kt} (100%) delete mode 100644 kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/asm.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt diff --git a/kmath-asm/build.gradle.kts b/kmath-asm/build.gradle.kts deleted file mode 100644 index 3b004eb8e..000000000 --- a/kmath-asm/build.gradle.kts +++ /dev/null @@ -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")) -} diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressionSpaces.kt b/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressionSpaces.kt deleted file mode 100644 index 0f8f685eb..000000000 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressionSpaces.kt +++ /dev/null @@ -1,74 +0,0 @@ -package scientifik.kmath.expressions.asm - -import scientifik.kmath.expressions.ExpressionAlgebra -import scientifik.kmath.operations.* - -open class AsmExpressionAlgebra(val algebra: Algebra) : - Algebra>, - ExpressionAlgebra> { - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override fun const(value: T): AsmExpression = AsmConstantExpression(value) - override fun variable(name: String, default: T?): AsmExpression = AsmVariableExpression(name, default) -} - -open class AsmExpressionSpace( - val space: Space -) : AsmExpressionAlgebra(space), Space> { - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override val zero: AsmExpression = AsmConstantExpression(space.zero) - - override fun add(a: AsmExpression, b: AsmExpression): AsmExpression = - AsmBinaryOperation(space, SpaceOperations.PLUS_OPERATION, a, b) - - override fun multiply(a: AsmExpression, k: Number): AsmExpression = AsmConstProductExpression(space, a, k) - operator fun AsmExpression.plus(arg: T): AsmExpression = this + const(arg) - operator fun AsmExpression.minus(arg: T): AsmExpression = this - const(arg) - operator fun T.plus(arg: AsmExpression): AsmExpression = arg + this - operator fun T.minus(arg: AsmExpression): AsmExpression = arg - this -} - -open class AsmExpressionRing(private val ring: Ring) : AsmExpressionSpace(ring), Ring> { - override val one: AsmExpression - get() = const(this.ring.one) - - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override fun number(value: Number): AsmExpression = const(ring { one * value }) - - override fun multiply(a: AsmExpression, b: AsmExpression): AsmExpression = - AsmBinaryOperation(space, RingOperations.TIMES_OPERATION, a, b) - - operator fun AsmExpression.times(arg: T): AsmExpression = this * const(arg) - operator fun T.times(arg: AsmExpression): AsmExpression = arg * this -} - -open class AsmExpressionField(private val field: Field) : - AsmExpressionRing(field), - Field> { - - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override fun divide(a: AsmExpression, b: AsmExpression): AsmExpression = - AsmBinaryOperation(field, FieldOperations.DIV_OPERATION, a, b) - - operator fun AsmExpression.div(arg: T): AsmExpression = this / const(arg) - operator fun T.div(arg: AsmExpression): AsmExpression = arg / this -} diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Builders.kt b/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Builders.kt deleted file mode 100644 index c56adb767..000000000 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Builders.kt +++ /dev/null @@ -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 >> asm( - i: E, - algebra: Algebra, - block: E.() -> AsmExpression -): Expression { - val expression = i.block().optimize() - val ctx = AsmGenerationContext(T::class.java, algebra, buildName(expression)) - expression.invoke(ctx) - return ctx.generate() -} - -inline fun buildAsmAlgebra( - algebra: Algebra, - block: AsmExpressionAlgebra.() -> AsmExpression -): Expression = asm(AsmExpressionAlgebra(algebra), algebra, block) - -inline fun buildAsmSpace( - algebra: Space, - block: AsmExpressionSpace.() -> AsmExpression -): Expression = asm(AsmExpressionSpace(algebra), algebra, block) - -inline fun buildAsmRing( - algebra: Ring, - block: AsmExpressionRing.() -> AsmExpression -): Expression = asm(AsmExpressionRing(algebra), algebra, block) - -inline fun buildAsmField( - algebra: Field, - block: AsmExpressionField.() -> AsmExpression -): Expression = asm(AsmExpressionField(algebra), algebra, block) diff --git a/kmath-asm/src/test/kotlin/scientifik/kmath/expressions/AsmTest.kt b/kmath-asm/src/test/kotlin/scientifik/kmath/expressions/AsmTest.kt deleted file mode 100644 index 034ba09c8..000000000 --- a/kmath-asm/src/test/kotlin/scientifik/kmath/expressions/AsmTest.kt +++ /dev/null @@ -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 = emptyMap(), - block: AsmExpressionField.() -> AsmExpression - ): 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)) } -} diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 88540e7b8..deb6a28ee 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -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{ + + 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")) } } -} \ No newline at end of file + + jvmTest { + dependencies { + implementation(kotlin("test")) + implementation(kotlin("test-junit5")) + } + } +} + +tasks.withType { useJUnitPlatform() } diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressions.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt similarity index 52% rename from kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressions.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt index 70f1fc28e..75b5f26d0 100644 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmExpressions.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt @@ -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( } } -internal class AsmVariableExpression(private val name: String, private val default: T? = null) : AsmExpression { +internal class AsmVariableExpression(private val name: String, private val default: T? = null) : + AsmExpression { override fun invoke(gen: AsmGenerationContext): Unit = gen.visitLoadFromVariables(name, default) } -internal class AsmConstantExpression(private val value: T) : AsmExpression { +internal class AsmConstantExpression(private val value: T) : + AsmExpression { override fun tryEvaluate(): T = value override fun invoke(gen: AsmGenerationContext): Unit = gen.visitLoadFromConstants(value) } @@ -141,9 +142,88 @@ internal class AsmConstProductExpression( } } +internal class AsmNumberExpression(private val context: NumericAlgebra, private val value: Number) : AsmExpression { + override fun tryEvaluate(): T? = context.number(value) + + override fun invoke(gen: AsmGenerationContext): Unit = gen.visitNumberConstant(value) +} + internal abstract class FunctionalCompiledExpression internal constructor( @JvmField protected val algebra: Algebra, @JvmField protected val constants: Array ) : Expression { abstract override fun invoke(arguments: Map): T } + +interface AsmExpressionAlgebra> : NumericAlgebra>, + ExpressionAlgebra> { + val algebra: A + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, operation, left, right) + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + AsmUnaryOperation(algebra, operation, arg) + + override fun number(value: Number): AsmExpression = AsmNumberExpression(algebra, value) + override fun const(value: T): AsmExpression = AsmConstantExpression(value) + override fun variable(name: String, default: T?): AsmExpression = AsmVariableExpression(name, default) +} + +open class AsmExpressionSpace(override val algebra: A) : AsmExpressionAlgebra, + Space> where A : Space, A : NumericAlgebra { + override val zero: AsmExpression + get() = const(algebra.zero) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, operation, left, right) + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + AsmUnaryOperation(algebra, operation, arg) + + override fun add(a: AsmExpression, b: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) + + override fun multiply(a: AsmExpression, k: Number): AsmExpression = AsmConstProductExpression(algebra, a, k) + operator fun AsmExpression.plus(arg: T): AsmExpression = this + const(arg) + operator fun AsmExpression.minus(arg: T): AsmExpression = this - const(arg) + operator fun T.plus(arg: AsmExpression): AsmExpression = arg + this + operator fun T.minus(arg: AsmExpression): AsmExpression = arg - this +} + +open class AsmExpressionRing(override val algebra: A) : AsmExpressionSpace(algebra), + Ring> where A : Ring, A : NumericAlgebra { + override val one: AsmExpression + get() = const(algebra.one) + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + AsmUnaryOperation(algebra, operation, arg) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, operation, left, right) + + override fun number(value: Number): AsmExpression = const(algebra { one * value }) + + override fun multiply(a: AsmExpression, b: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) + + operator fun AsmExpression.times(arg: T): AsmExpression = this * const(arg) + operator fun T.times(arg: AsmExpression): AsmExpression = arg * this +} + +open class AsmExpressionField(override val algebra: A) : + AsmExpressionRing(algebra), + Field> where A : Field, A : NumericAlgebra { + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + AsmUnaryOperation(algebra, operation, arg) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, operation, left, right) + + override fun divide(a: AsmExpression, b: AsmExpression): AsmExpression = + AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) + + operator fun AsmExpression.div(arg: T): AsmExpression = this / const(arg) + operator fun T.div(arg: AsmExpression): AsmExpression = arg / this +} + diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmGenerationContext.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt similarity index 96% rename from kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmGenerationContext.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt index 92663ba8f..d9dba746d 100644 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/AsmGenerationContext.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt @@ -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( 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( } 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( ) 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" diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt new file mode 100644 index 000000000..67870e07e --- /dev/null +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt @@ -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 AsmExpression.compile(algebra: Algebra): Expression { + val ctx = AsmGenerationContext(T::class.java, algebra, buildName(this)) + invoke(ctx) + return ctx.generate() +} + +inline fun , E : AsmExpressionAlgebra> A.asm( + expressionAlgebra: E, + block: E.() -> AsmExpression +): Expression = expressionAlgebra.block().compile(expressionAlgebra.algebra) + +inline fun , E : AsmExpressionAlgebra> A.asm( + expressionAlgebra: E, + ast: MST +): Expression = asm(expressionAlgebra) { evaluate(ast) } + +inline fun A.asmSpace(block: AsmExpressionSpace.() -> AsmExpression): Expression where A : NumericAlgebra, A : Space = + AsmExpressionSpace(this).let { it.block().compile(it.algebra) } + +inline fun A.asmSpace(ast: MST): Expression where A : NumericAlgebra, A : Space = + asmSpace { evaluate(ast) } + +inline fun A.asmRing(block: AsmExpressionRing.() -> AsmExpression): Expression where A : NumericAlgebra, A : Ring = + AsmExpressionRing(this).let { it.block().compile(it.algebra) } + +inline fun A.asmRing(ast: MST): Expression where A : NumericAlgebra, A : Ring = + asmRing { evaluate(ast) } + +inline fun A.asmField(block: AsmExpressionField.() -> AsmExpression): Expression where A : NumericAlgebra, A : Field = + AsmExpressionField(this).let { it.block().compile(it.algebra) } + +inline fun A.asmField(ast: MST): Expression where A : NumericAlgebra, A : Field = + asmRing { evaluate(ast) } diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/MethodVisitors.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt similarity index 94% rename from kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/MethodVisitors.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt index 9f697ab6d..42565b6ba 100644 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/MethodVisitors.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.expressions.asm +package scientifik.kmath.asm import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes.* diff --git a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Optimization.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt similarity index 80% rename from kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Optimization.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt index bcd182dc3..e821bd206 100644 --- a/kmath-asm/src/main/kotlin/scientifik/kmath/expressions/asm/Optimization.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.expressions.asm +package scientifik.kmath.asm @PublishedApi internal fun AsmExpression.optimize(): AsmExpression { diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/Parser.kt similarity index 100% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/Parser.kt diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/asm.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/asm.kt deleted file mode 100644 index c01648fb0..000000000 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/asm.kt +++ /dev/null @@ -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 - -interface AsmExpressionAlgebra> : NumericAlgebra> { - val algebra: A -} - -fun AsmExpression.compile(): Expression = TODO() - -//TODO add converter for functional expressions - -inline fun > A.asm( - block: AsmExpressionAlgebra.() -> AsmExpression -): Expression = TODO() - -inline fun > A.asm(ast: MST): Expression = asm { evaluate(ast) } \ No newline at end of file diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt new file mode 100644 index 000000000..73058face --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt @@ -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) + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt index 6849d24b8..ddac07786 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt @@ -1,17 +1,17 @@ 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{ +internal class ParserTest { @Test - fun parsedExpression(){ + fun parsedExpression() { val mst = "2+2*(2+2)".parseMath() val res = ComplexField.evaluate(mst) - assertEquals(Complex(10.0,0.0), res) + assertEquals(Complex(10.0, 0.0), res) } -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt index b2e4d8a3d..cdd6f695b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt @@ -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 Algebra.buildExpression(block: FunctionalExpressionAlgebra.() -> Expression): Expression = - FunctionalExpressionAlgebra(this).run(block) - /** * Create a functional expression on this [Space] */ -fun Space.buildExpression(block: FunctionalExpressionSpace.() -> Expression): Expression = +fun Space.buildExpression(block: FunctionalExpressionSpace>.() -> Expression): Expression = FunctionalExpressionSpace(this).run(block) /** * Create a functional expression on this [Ring] */ -fun Ring.buildExpression(block: FunctionalExpressionRing.() -> Expression): Expression = +fun Ring.buildExpression(block: FunctionalExpressionRing>.() -> Expression): Expression = FunctionalExpressionRing(this).run(block) /** * Create a functional expression on this [Field] */ -fun Field.buildExpression(block: FunctionalExpressionField.() -> Expression): Expression = +fun Field.buildExpression(block: FunctionalExpressionField>.() -> Expression): Expression = FunctionalExpressionField(this).run(block) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt index cbbdb99f5..88d8c87b7 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt @@ -26,48 +26,55 @@ internal class FunctionalConstantExpression(val value: T) : Expression { override fun invoke(arguments: Map): T = value } -internal class FunctionalConstProductExpression(val context: Space, val expr: Expression, val const: Number) : +internal class FunctionalConstProductExpression( + val context: Space, + val expr: Expression, + val const: Number +) : Expression { override fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) } -open class FunctionalExpressionAlgebra(val algebra: Algebra) : - Algebra>, - ExpressionAlgebra> { - override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) +interface FunctionalExpressionAlgebra> : ExpressionAlgebra> { + val algebra: A override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = FunctionalBinaryOperation(algebra, operation, left, right) + override fun unaryOperation(operation: String, arg: Expression): Expression = + FunctionalUnaryOperation(algebra, operation, arg) + override fun const(value: T): Expression = FunctionalConstantExpression(value) override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) } -open class FunctionalExpressionSpace(val space: Space) : - FunctionalExpressionAlgebra(space), - Space> { - override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) +open class FunctionalExpressionSpace(override val algebra: A) : FunctionalExpressionAlgebra, + Space> where A : Space { + override val zero: Expression + get() = const(algebra.zero) override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = FunctionalBinaryOperation(algebra, operation, left, right) - override val zero: Expression = FunctionalConstantExpression(space.zero) + override fun unaryOperation(operation: String, arg: Expression): Expression = + FunctionalUnaryOperation(algebra, operation, arg) override fun add(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(space, SpaceOperations.PLUS_OPERATION, a, b) + FunctionalBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) + + override fun multiply(a: Expression, k: Number): Expression = + FunctionalConstProductExpression(algebra, a, k) - override fun multiply(a: Expression, k: Number): Expression = FunctionalConstProductExpression(space, a, k) operator fun Expression.plus(arg: T): Expression = this + const(arg) operator fun Expression.minus(arg: T): Expression = this - const(arg) operator fun T.plus(arg: Expression): Expression = arg + this operator fun T.minus(arg: Expression): Expression = arg - this } -open class FunctionalExpressionRing(val ring: Ring) : FunctionalExpressionSpace(ring), Ring> { +open class FunctionalExpressionRing(override val algebra: A) : FunctionalExpressionSpace(algebra), + Ring> where A : Ring, A : NumericAlgebra { override val one: Expression - get() = const(this.ring.one) + get() = const(algebra.one) override fun unaryOperation(operation: String, arg: Expression): Expression = FunctionalUnaryOperation(algebra, operation, arg) @@ -75,18 +82,18 @@ open class FunctionalExpressionRing(val ring: Ring) : FunctionalExpression override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = FunctionalBinaryOperation(algebra, operation, left, right) - override fun number(value: Number): Expression = const(ring { one * value }) + override fun number(value: Number): Expression = const(algebra { one * value }) override fun multiply(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(space, RingOperations.TIMES_OPERATION, a, b) + FunctionalBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) operator fun Expression.times(arg: T): Expression = this * const(arg) operator fun T.times(arg: Expression): Expression = arg * this } -open class FunctionalExpressionField(val field: Field) : - FunctionalExpressionRing(field), - Field> { +open class FunctionalExpressionField(override val algebra: A) : + FunctionalExpressionRing(algebra), + Field> where A : Field, A : NumericAlgebra { override fun unaryOperation(operation: String, arg: Expression): Expression = FunctionalUnaryOperation(algebra, operation, arg) @@ -95,7 +102,7 @@ open class FunctionalExpressionField(val field: Field) : FunctionalBinaryOperation(algebra, operation, left, right) override fun divide(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(space, FieldOperations.DIV_OPERATION, a, b) + FunctionalBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) operator fun Expression.div(arg: T): Expression = this / const(arg) operator fun T.div(arg: Expression): Expression = arg / this diff --git a/settings.gradle.kts b/settings.gradle.kts index 2b2633060..465ecfca8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -45,6 +45,5 @@ include( ":kmath-for-real", ":kmath-geometry", ":kmath-ast", - ":kmath-asm", ":examples" )