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:
Iaroslav 2020-06-13 02:26:12 +07:00
parent b902f3980a
commit 3ec1f7b5f1
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
17 changed files with 220 additions and 260 deletions

View File

@ -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"))
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)) }
}

View File

@ -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() }

View File

@ -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
}

View File

@ -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"

View File

@ -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) }

View File

@ -1,4 +1,4 @@
package scientifik.kmath.expressions.asm
package scientifik.kmath.asm
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes.*

View File

@ -1,4 +1,4 @@
package scientifik.kmath.expressions.asm
package scientifik.kmath.asm
@PublishedApi
internal fun <T> AsmExpression<T>.optimize(): AsmExpression<T> {

View File

@ -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) }

View 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)
}
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -45,6 +45,5 @@ include(
":kmath-for-real",
":kmath-geometry",
":kmath-ast",
":kmath-asm",
":examples"
)