forked from kscience/kmath
Move asm dependency to implementation configuration; rename many ASM API classes, make AsmCompiledExpression implement functional Expression, fix typos, encapsulate AsmGenerationContext
This commit is contained in:
parent
a2e33bf6d8
commit
6ac0297530
@ -4,6 +4,6 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
api(project(path = ":kmath-core"))
|
||||
api("org.ow2.asm:asm:8.0.1")
|
||||
api("org.ow2.asm:asm-commons:8.0.1")
|
||||
implementation("org.ow2.asm:asm:8.0.1")
|
||||
implementation("org.ow2.asm:asm-commons:8.0.1")
|
||||
}
|
||||
|
@ -8,11 +8,30 @@ import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.operations.Field
|
||||
import scientifik.kmath.operations.Space
|
||||
|
||||
abstract class AsmCompiled<T>(@JvmField val algebra: Algebra<T>, @JvmField val constants: MutableList<out Any>) {
|
||||
abstract fun evaluate(arguments: Map<String, T>): T
|
||||
abstract class AsmCompiledExpression<T> internal constructor(
|
||||
@JvmField val algebra: Algebra<T>,
|
||||
@JvmField val constants: MutableList<out Any>
|
||||
) : Expression<T> {
|
||||
abstract override fun invoke(arguments: Map<String, T>): T
|
||||
}
|
||||
|
||||
class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T>, private val className: String) {
|
||||
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)
|
||||
}
|
||||
|
||||
class AsmGenerationContext<T>(
|
||||
classOfT: Class<*>,
|
||||
private val algebra: Algebra<T>,
|
||||
private val className: String
|
||||
) {
|
||||
private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) {
|
||||
internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size)
|
||||
}
|
||||
@ -26,30 +45,23 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
private val T_CLASS: String = classOfT.name.replace('.', '/')
|
||||
|
||||
private val slashesClassName: String = className.replace(oldChar = '.', newChar = '/')
|
||||
private val evaluateThisVar: Int = 0
|
||||
private val evaluateArgumentsVar: Int = 1
|
||||
private val invokeThisVar: Int = 0
|
||||
private val invokeArgumentsVar: Int = 1
|
||||
private var maxStack: Int = 0
|
||||
private lateinit var constants: MutableList<Any>
|
||||
private lateinit var asmCompiledClassWriter: ClassWriter
|
||||
private lateinit var evaluateMethodVisitor: MethodVisitor
|
||||
private lateinit var evaluateL0: Label
|
||||
private lateinit var evaluateL1: Label
|
||||
private val constants: MutableList<Any> = mutableListOf()
|
||||
private val asmCompiledClassWriter: ClassWriter = ClassWriter(0)
|
||||
private val invokeMethodVisitor: MethodVisitor
|
||||
private val invokeL0: Label
|
||||
private lateinit var invokeL1: Label
|
||||
private var generatedInstance: AsmCompiledExpression<T>? = null
|
||||
|
||||
init {
|
||||
start()
|
||||
}
|
||||
|
||||
fun start() {
|
||||
constants = mutableListOf()
|
||||
asmCompiledClassWriter = ClassWriter(0)
|
||||
maxStack = 0
|
||||
|
||||
asmCompiledClassWriter.visit(
|
||||
V1_8,
|
||||
ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
|
||||
slashesClassName,
|
||||
"L$ASM_COMPILED_CLASS<L$T_CLASS;>;",
|
||||
ASM_COMPILED_CLASS,
|
||||
"L$ASM_COMPILED_EXPRESSION_CLASS<L$T_CLASS;>;",
|
||||
ASM_COMPILED_EXPRESSION_CLASS,
|
||||
arrayOf()
|
||||
)
|
||||
|
||||
@ -66,7 +78,7 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
|
||||
visitMethodInsn(
|
||||
INVOKESPECIAL,
|
||||
ASM_COMPILED_CLASS,
|
||||
ASM_COMPILED_EXPRESSION_CLASS,
|
||||
"<init>",
|
||||
"(L$ALGEBRA_CLASS;L$LIST_CLASS;)V",
|
||||
false
|
||||
@ -93,45 +105,48 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
visitEnd()
|
||||
}
|
||||
|
||||
evaluateMethodVisitor = visitMethod(
|
||||
invokeMethodVisitor = visitMethod(
|
||||
ACC_PUBLIC or ACC_FINAL,
|
||||
"evaluate",
|
||||
"invoke",
|
||||
"(L$MAP_CLASS;)L$T_CLASS;",
|
||||
"(L$MAP_CLASS<L$STRING_CLASS;+L$T_CLASS;>;)L$T_CLASS;",
|
||||
null
|
||||
)
|
||||
|
||||
evaluateMethodVisitor.run {
|
||||
invokeMethodVisitor.run {
|
||||
visitCode()
|
||||
evaluateL0 = Label()
|
||||
visitLabel(evaluateL0)
|
||||
invokeL0 = Label()
|
||||
visitLabel(invokeL0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun generate(): AsmCompiled<T> {
|
||||
evaluateMethodVisitor.run {
|
||||
internal fun generate(): AsmCompiledExpression<T> {
|
||||
generatedInstance?.let { return it }
|
||||
|
||||
invokeMethodVisitor.run {
|
||||
visitInsn(ARETURN)
|
||||
evaluateL1 = Label()
|
||||
visitLabel(evaluateL1)
|
||||
invokeL1 = Label()
|
||||
visitLabel(invokeL1)
|
||||
|
||||
visitLocalVariable(
|
||||
"this",
|
||||
"L$slashesClassName;",
|
||||
T_CLASS,
|
||||
evaluateL0,
|
||||
evaluateL1,
|
||||
evaluateThisVar
|
||||
invokeL0,
|
||||
invokeL1,
|
||||
invokeThisVar
|
||||
)
|
||||
|
||||
visitLocalVariable(
|
||||
"arguments",
|
||||
"L$MAP_CLASS;",
|
||||
"L$MAP_CLASS<L$STRING_CLASS;+L$T_CLASS;>;",
|
||||
evaluateL0,
|
||||
evaluateL1,
|
||||
evaluateArgumentsVar
|
||||
invokeL0,
|
||||
invokeL1,
|
||||
invokeArgumentsVar
|
||||
)
|
||||
|
||||
visitMaxs(maxStack + 1, 2)
|
||||
@ -140,7 +155,7 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
|
||||
asmCompiledClassWriter.visitMethod(
|
||||
ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC,
|
||||
"evaluate",
|
||||
"invoke",
|
||||
"(L$MAP_CLASS;)L$OBJECT_CLASS;",
|
||||
null,
|
||||
null
|
||||
@ -151,7 +166,7 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
visitLabel(l0)
|
||||
visitVarInsn(ALOAD, 0)
|
||||
visitVarInsn(ALOAD, 1)
|
||||
visitMethodInsn(INVOKEVIRTUAL, slashesClassName, "evaluate", "(L$MAP_CLASS;)L$T_CLASS;", false)
|
||||
visitMethodInsn(INVOKEVIRTUAL, slashesClassName, "invoke", "(L$MAP_CLASS;)L$T_CLASS;", false)
|
||||
visitInsn(ARETURN)
|
||||
val l1 = Label()
|
||||
visitLabel(l1)
|
||||
@ -171,31 +186,34 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
|
||||
asmCompiledClassWriter.visitEnd()
|
||||
|
||||
return classLoader
|
||||
val new = classLoader
|
||||
.defineClass(className, asmCompiledClassWriter.toByteArray())
|
||||
.constructors
|
||||
.first()
|
||||
.newInstance(algebra, constants) as AsmCompiled<T>
|
||||
.newInstance(algebra, constants) as AsmCompiledExpression<T>
|
||||
|
||||
generatedInstance = new
|
||||
return new
|
||||
}
|
||||
|
||||
fun visitLoadFromConstants(value: T) = visitLoadAnyFromConstants(value as Any, T_CLASS)
|
||||
internal fun visitLoadFromConstants(value: T) = visitLoadAnyFromConstants(value as Any, T_CLASS)
|
||||
|
||||
fun visitLoadAnyFromConstants(value: Any, type: String) {
|
||||
private fun visitLoadAnyFromConstants(value: Any, type: String) {
|
||||
val idx = if (value in constants) constants.indexOf(value) else constants.apply { add(value) }.lastIndex
|
||||
maxStack++
|
||||
|
||||
evaluateMethodVisitor.run {
|
||||
invokeMethodVisitor.run {
|
||||
visitLoadThis()
|
||||
visitFieldInsn(GETFIELD, slashesClassName, "constants", "L$LIST_CLASS;")
|
||||
visitLdcOrIConstInsn(idx)
|
||||
visitMethodInsn(INVOKEINTERFACE, LIST_CLASS, "get", "(I)L$OBJECT_CLASS;", true)
|
||||
evaluateMethodVisitor.visitTypeInsn(CHECKCAST, type)
|
||||
invokeMethodVisitor.visitTypeInsn(CHECKCAST, type)
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitLoadThis(): Unit = evaluateMethodVisitor.visitVarInsn(ALOAD, evaluateThisVar)
|
||||
private fun visitLoadThis(): Unit = invokeMethodVisitor.visitVarInsn(ALOAD, invokeThisVar)
|
||||
|
||||
fun visitNumberConstant(value: Number) {
|
||||
internal fun visitNumberConstant(value: Number) {
|
||||
maxStack++
|
||||
val clazz = value.javaClass
|
||||
val c = clazz.name.replace('.', '/')
|
||||
@ -204,22 +222,22 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
|
||||
if (sigLetter != null) {
|
||||
when (value) {
|
||||
is Int -> evaluateMethodVisitor.visitLdcOrIConstInsn(value)
|
||||
is Double -> evaluateMethodVisitor.visitLdcOrDConstInsn(value)
|
||||
is Float -> evaluateMethodVisitor.visitLdcOrFConstInsn(value)
|
||||
else -> evaluateMethodVisitor.visitLdcInsn(value)
|
||||
is Int -> invokeMethodVisitor.visitLdcOrIConstInsn(value)
|
||||
is Double -> invokeMethodVisitor.visitLdcOrDConstInsn(value)
|
||||
is Float -> invokeMethodVisitor.visitLdcOrFConstInsn(value)
|
||||
else -> invokeMethodVisitor.visitLdcInsn(value)
|
||||
}
|
||||
|
||||
evaluateMethodVisitor.visitMethodInsn(INVOKESTATIC, c, "valueOf", "($sigLetter)L${c};", false)
|
||||
invokeMethodVisitor.visitMethodInsn(INVOKESTATIC, c, "valueOf", "($sigLetter)L${c};", false)
|
||||
return
|
||||
}
|
||||
|
||||
visitLoadAnyFromConstants(value, c)
|
||||
}
|
||||
|
||||
fun visitLoadFromVariables(name: String, defaultValue: T? = null) = evaluateMethodVisitor.run {
|
||||
internal fun visitLoadFromVariables(name: String, defaultValue: T? = null) = invokeMethodVisitor.run {
|
||||
maxStack += 2
|
||||
visitVarInsn(ALOAD, evaluateArgumentsVar)
|
||||
visitVarInsn(ALOAD, invokeArgumentsVar)
|
||||
|
||||
if (defaultValue != null) {
|
||||
visitLdcInsn(name)
|
||||
@ -242,26 +260,26 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
visitCastToT()
|
||||
}
|
||||
|
||||
fun visitLoadAlgebra() {
|
||||
evaluateMethodVisitor.visitVarInsn(ALOAD, evaluateThisVar)
|
||||
internal fun visitLoadAlgebra() {
|
||||
invokeMethodVisitor.visitVarInsn(ALOAD, invokeThisVar)
|
||||
|
||||
evaluateMethodVisitor.visitFieldInsn(
|
||||
invokeMethodVisitor.visitFieldInsn(
|
||||
GETFIELD,
|
||||
ASM_COMPILED_CLASS, "algebra", "L$ALGEBRA_CLASS;"
|
||||
ASM_COMPILED_EXPRESSION_CLASS, "algebra", "L$ALGEBRA_CLASS;"
|
||||
)
|
||||
|
||||
evaluateMethodVisitor.visitTypeInsn(CHECKCAST, T_ALGEBRA_CLASS)
|
||||
invokeMethodVisitor.visitTypeInsn(CHECKCAST, T_ALGEBRA_CLASS)
|
||||
}
|
||||
|
||||
fun visitAlgebraOperation(owner: String, method: String, descriptor: String) {
|
||||
internal fun visitAlgebraOperation(owner: String, method: String, descriptor: String) {
|
||||
maxStack++
|
||||
evaluateMethodVisitor.visitMethodInsn(INVOKEINTERFACE, owner, method, descriptor, true)
|
||||
invokeMethodVisitor.visitMethodInsn(INVOKEINTERFACE, owner, method, descriptor, true)
|
||||
visitCastToT()
|
||||
}
|
||||
|
||||
private fun visitCastToT(): Unit = evaluateMethodVisitor.visitTypeInsn(CHECKCAST, T_CLASS)
|
||||
private fun visitCastToT(): Unit = invokeMethodVisitor.visitTypeInsn(CHECKCAST, T_CLASS)
|
||||
|
||||
companion object {
|
||||
internal companion object {
|
||||
private val SIGNATURE_LETTERS = mapOf(
|
||||
java.lang.Byte::class.java to "B",
|
||||
java.lang.Short::class.java to "S",
|
||||
@ -271,16 +289,16 @@ class AsmGenerationContext<T>(classOfT: Class<*>, private val algebra: Algebra<T
|
||||
java.lang.Double::class.java to "D"
|
||||
)
|
||||
|
||||
const val ASM_COMPILED_CLASS = "scientifik/kmath/expressions/AsmCompiled"
|
||||
const val LIST_CLASS = "java/util/List"
|
||||
const val MAP_CLASS = "java/util/Map"
|
||||
const val OBJECT_CLASS = "java/lang/Object"
|
||||
const val ALGEBRA_CLASS = "scientifik/kmath/operations/Algebra"
|
||||
const val SPACE_OPERATIONS_CLASS = "scientifik/kmath/operations/SpaceOperations"
|
||||
const val STRING_CLASS = "java/lang/String"
|
||||
const val FIELD_OPERATIONS_CLASS = "scientifik/kmath/operations/FieldOperations"
|
||||
const val RING_OPERATIONS_CLASS = "scientifik/kmath/operations/RingOperations"
|
||||
const val NUMBER_CLASS = "java/lang/Number"
|
||||
internal const val ASM_COMPILED_EXPRESSION_CLASS = "scientifik/kmath/expressions/AsmCompiledExpression"
|
||||
internal const val LIST_CLASS = "java/util/List"
|
||||
internal const val MAP_CLASS = "java/util/Map"
|
||||
internal const val OBJECT_CLASS = "java/lang/Object"
|
||||
internal const val ALGEBRA_CLASS = "scientifik/kmath/operations/Algebra"
|
||||
internal const val SPACE_OPERATIONS_CLASS = "scientifik/kmath/operations/SpaceOperations"
|
||||
internal const val STRING_CLASS = "java/lang/String"
|
||||
internal const val FIELD_OPERATIONS_CLASS = "scientifik/kmath/operations/FieldOperations"
|
||||
internal const val RING_OPERATIONS_CLASS = "scientifik/kmath/operations/RingOperations"
|
||||
internal const val NUMBER_CLASS = "java/lang/Number"
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,43 +384,25 @@ internal class AsmDivExpression<T>(
|
||||
}
|
||||
}
|
||||
|
||||
open class AsmFunctionalExpressionSpace<T>(
|
||||
val space: Space<T>,
|
||||
one: T
|
||||
) : Space<AsmExpression<T>>,
|
||||
open class AsmExpressionSpace<T>(space: Space<T>) : Space<AsmExpression<T>>,
|
||||
ExpressionSpace<T, AsmExpression<T>> {
|
||||
override val zero: AsmExpression<T> =
|
||||
AsmConstantExpression(space.zero)
|
||||
|
||||
override fun const(value: T): AsmExpression<T> =
|
||||
AsmConstantExpression(value)
|
||||
|
||||
override fun variable(name: String, default: T?): AsmExpression<T> =
|
||||
AsmVariableExpression(
|
||||
name,
|
||||
default
|
||||
)
|
||||
|
||||
override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmSumExpression(a, b)
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> =
|
||||
AsmConstProductExpression(a, k)
|
||||
|
||||
|
||||
override val zero: AsmExpression<T> = AsmConstantExpression(space.zero)
|
||||
override fun const(value: T): AsmExpression<T> = AsmConstantExpression(value)
|
||||
override fun variable(name: String, default: T?): AsmExpression<T> = AsmVariableExpression(name, default)
|
||||
override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> = AsmSumExpression(a, b)
|
||||
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> = AsmConstProductExpression(a, k)
|
||||
operator fun AsmExpression<T>.plus(arg: T) = this + const(arg)
|
||||
operator fun AsmExpression<T>.minus(arg: T) = this - const(arg)
|
||||
|
||||
operator fun T.plus(arg: AsmExpression<T>) = arg + this
|
||||
operator fun T.minus(arg: AsmExpression<T>) = arg - this
|
||||
}
|
||||
|
||||
class AsmFunctionalExpressionField<T>(val field: Field<T>) : ExpressionField<T, AsmExpression<T>>,
|
||||
AsmFunctionalExpressionSpace<T>(field, field.one) {
|
||||
class AsmExpressionField<T>(private val field: Field<T>) : ExpressionField<T, AsmExpression<T>>,
|
||||
AsmExpressionSpace<T>(field) {
|
||||
override val one: AsmExpression<T>
|
||||
get() = const(this.field.one)
|
||||
|
||||
override fun const(value: Double): AsmExpression<T> = const(field.run { one * value })
|
||||
override fun number(value: Number): AsmExpression<T> = const(field.run { one * value })
|
||||
|
||||
override fun multiply(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||
AsmProductExpression(a, b)
|
||||
@ -412,7 +412,6 @@ class AsmFunctionalExpressionField<T>(val field: Field<T>) : ExpressionField<T,
|
||||
|
||||
operator fun AsmExpression<T>.times(arg: T) = this * const(arg)
|
||||
operator fun AsmExpression<T>.div(arg: T) = this / const(arg)
|
||||
|
||||
operator fun T.times(arg: AsmExpression<T>) = arg * this
|
||||
operator fun T.div(arg: AsmExpression<T>) = arg / this
|
||||
}
|
||||
|
@ -12,15 +12,12 @@ class AsmTest {
|
||||
arguments: Map<String, T>,
|
||||
algebra: Algebra<T>,
|
||||
clazz: Class<*>
|
||||
) {
|
||||
assertEquals(
|
||||
expectedValue, AsmGenerationContext(
|
||||
clazz,
|
||||
algebra,
|
||||
"TestAsmCompiled"
|
||||
).also(expr::invoke).generate().evaluate(arguments)
|
||||
)
|
||||
}
|
||||
): Unit = assertEquals(
|
||||
expectedValue, AsmGenerationContext(clazz, algebra, "TestAsmCompiled")
|
||||
.also(expr::invoke)
|
||||
.generate()
|
||||
.invoke(arguments)
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun testDoubleExpressionValue(
|
||||
@ -29,7 +26,7 @@ class AsmTest {
|
||||
arguments: Map<String, Double>,
|
||||
algebra: Algebra<Double> = RealField,
|
||||
clazz: Class<Double> = java.lang.Double::class.java as Class<Double>
|
||||
) = testExpressionValue(expectedValue, expr, arguments, algebra, clazz)
|
||||
): Unit = testExpressionValue(expectedValue, expr, arguments, algebra, clazz)
|
||||
|
||||
@Test
|
||||
fun testSum() = testDoubleExpressionValue(
|
||||
@ -39,28 +36,28 @@ class AsmTest {
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testConst() = testDoubleExpressionValue(
|
||||
fun testConst(): Unit = testDoubleExpressionValue(
|
||||
123.0,
|
||||
AsmConstantExpression(123.0),
|
||||
mapOf()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testDiv() = testDoubleExpressionValue(
|
||||
fun testDiv(): Unit = testDoubleExpressionValue(
|
||||
0.5,
|
||||
AsmDivExpression(AsmConstantExpression(1.0), AsmConstantExpression(2.0)),
|
||||
mapOf()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testProduct() = testDoubleExpressionValue(
|
||||
fun testProduct(): Unit = testDoubleExpressionValue(
|
||||
25.0,
|
||||
AsmProductExpression(AsmVariableExpression("x"), AsmVariableExpression("x")),
|
||||
mapOf("x" to 5.0)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testCProduct() = testDoubleExpressionValue(
|
||||
fun testCProduct(): Unit = testDoubleExpressionValue(
|
||||
25.0,
|
||||
AsmConstProductExpression(AsmVariableExpression("x"), 5.0),
|
||||
mapOf("x" to 5.0)
|
||||
|
@ -76,7 +76,7 @@ interface ExpressionSpace<T, E> : Space<E>, ExpressionContext<T, E> {
|
||||
}
|
||||
|
||||
interface ExpressionField<T, E> : Field<E>, ExpressionSpace<T, E> {
|
||||
fun const(value: Double): E = one.times(value)
|
||||
fun number(value: Number): E = one * value
|
||||
|
||||
override fun produce(node: SyntaxTreeNode): E {
|
||||
if (node is BinaryNode) {
|
||||
|
@ -27,55 +27,41 @@ internal class ProductExpression<T>(val context: Ring<T>, val first: Expression<
|
||||
context.multiply(first.invoke(arguments), second.invoke(arguments))
|
||||
}
|
||||
|
||||
internal class ConstProductExpession<T>(val context: Space<T>, val expr: Expression<T>, val const: Number) :
|
||||
internal class ConstProductExpression<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)
|
||||
}
|
||||
|
||||
internal class DivExpession<T>(val context: Field<T>, val expr: Expression<T>, val second: Expression<T>) :
|
||||
internal class DivExpression<T>(val context: Field<T>, val expr: Expression<T>, val second: Expression<T>) :
|
||||
Expression<T> {
|
||||
override fun invoke(arguments: Map<String, T>): T = context.divide(expr.invoke(arguments), second.invoke(arguments))
|
||||
}
|
||||
|
||||
open class FunctionalExpressionSpace<T>(
|
||||
val space: Space<T>,
|
||||
one: T
|
||||
) : Space<Expression<T>>, ExpressionSpace<T,Expression<T>> {
|
||||
|
||||
open class FunctionalExpressionSpace<T>(val space: Space<T>) : Space<Expression<T>>, ExpressionSpace<T, Expression<T>> {
|
||||
override val zero: Expression<T> = ConstantExpression(space.zero)
|
||||
|
||||
override fun const(value: T): Expression<T> = ConstantExpression(value)
|
||||
|
||||
override fun variable(name: String, default: T?): Expression<T> = VariableExpression(name, default)
|
||||
|
||||
override fun add(a: Expression<T>, b: Expression<T>): Expression<T> = SumExpression(space, a, b)
|
||||
|
||||
override fun multiply(a: Expression<T>, k: Number): Expression<T> = ConstProductExpession(space, a, k)
|
||||
|
||||
|
||||
operator fun Expression<T>.plus(arg: T) = this + const(arg)
|
||||
operator fun Expression<T>.minus(arg: T) = this - const(arg)
|
||||
|
||||
operator fun T.plus(arg: Expression<T>) = arg + this
|
||||
operator fun T.minus(arg: Expression<T>) = arg - this
|
||||
override fun multiply(a: Expression<T>, k: Number): Expression<T> = ConstProductExpression(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 FunctionalExpressionField<T>(
|
||||
val field: Field<T>
|
||||
) : ExpressionField<T,Expression<T>>, FunctionalExpressionSpace<T>(field, field.one) {
|
||||
) : ExpressionField<T, Expression<T>>, FunctionalExpressionSpace<T>(field) {
|
||||
|
||||
override val one: Expression<T>
|
||||
get() = const(this.field.one)
|
||||
|
||||
override fun const(value: Double): Expression<T> = const(field.run { one*value})
|
||||
|
||||
override fun number(value: Number): Expression<T> = const(field.run { one * value })
|
||||
override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> = ProductExpression(field, a, b)
|
||||
|
||||
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> = DivExpession(field, a, b)
|
||||
|
||||
operator fun Expression<T>.times(arg: T) = this * const(arg)
|
||||
operator fun Expression<T>.div(arg: T) = this / const(arg)
|
||||
|
||||
operator fun T.times(arg: Expression<T>) = arg * this
|
||||
operator fun T.div(arg: Expression<T>) = arg / this
|
||||
}
|
||||
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> = DivExpression(field, a, b)
|
||||
operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
|
||||
operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
|
||||
operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
||||
operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user