Minor refactor and document

This commit is contained in:
Iaroslav 2020-06-13 15:44:54 +07:00
parent 3ec1f7b5f1
commit 36ad1fcf58
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
3 changed files with 141 additions and 56 deletions

View File

@ -142,7 +142,8 @@ internal class AsmConstProductExpression<T>(
} }
} }
internal class AsmNumberExpression<T>(private val context: NumericAlgebra<T>, private val value: Number) : AsmExpression<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 tryEvaluate(): T? = context.number(value)
override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitNumberConstant(value) override fun invoke(gen: AsmGenerationContext<T>): Unit = gen.visitNumberConstant(value)
@ -155,75 +156,121 @@ internal abstract class FunctionalCompiledExpression<T> internal constructor(
abstract override fun invoke(arguments: Map<String, T>): T abstract override fun invoke(arguments: Map<String, T>): T
} }
/**
* A context class for [AsmExpression] construction.
*/
interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmExpression<T>>, interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmExpression<T>>,
ExpressionAlgebra<T, AsmExpression<T>> { ExpressionAlgebra<T, AsmExpression<T>> {
/**
* The algebra to provide for AsmExpressions built.
*/
val algebra: A val algebra: A
/**
* Builds an AsmExpression to wrap a number.
*/
override fun number(value: Number): AsmExpression<T> = AsmNumberExpression(algebra, value)
/**
* Builds an AsmExpression of constant expression which does not depend on arguments.
*/
override fun const(value: T): AsmExpression<T> = AsmConstantExpression(value)
/**
* Builds an AsmExpression to access a variable.
*/
override fun variable(name: String, default: T?): AsmExpression<T> = AsmVariableExpression(name, default)
/**
* Builds an AsmExpression of dynamic call of binary operation [operation] on [left] and [right].
*/
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> = override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
AsmBinaryOperation(algebra, operation, left, right) AsmBinaryOperation(algebra, operation, left, right)
/**
* Builds an AsmExpression of dynamic call of unary operation with name [operation] on [arg].
*/
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> = override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
AsmUnaryOperation(algebra, operation, arg) 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)
} }
/**
* A context class for [AsmExpression] construction for [Space] algebras.
*/
open class AsmExpressionSpace<T, A>(override val algebra: A) : AsmExpressionAlgebra<T, A>, open class AsmExpressionSpace<T, A>(override val algebra: A) : AsmExpressionAlgebra<T, A>,
Space<AsmExpression<T>> where A : Space<T>, A : NumericAlgebra<T> { Space<AsmExpression<T>> where A : Space<T>, A : NumericAlgebra<T> {
override val zero: AsmExpression<T> override val zero: AsmExpression<T>
get() = const(algebra.zero) get() = const(algebra.zero)
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> = /**
AsmBinaryOperation(algebra, operation, left, right) * Builds an AsmExpression of addition of two another expressions.
*/
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> = override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
/**
* Builds an AsmExpression of multiplication of expression by number.
*/
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> = AsmConstProductExpression(algebra, a, k) 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>.plus(arg: T): AsmExpression<T> = this + const(arg)
operator fun AsmExpression<T>.minus(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.plus(arg: AsmExpression<T>): AsmExpression<T> = arg + this
operator fun T.minus(arg: AsmExpression<T>): AsmExpression<T> = arg - this operator fun T.minus(arg: AsmExpression<T>): AsmExpression<T> = arg - this
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionAlgebra>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionAlgebra>.binaryOperation(operation, left, right)
} }
/**
* A context class for [AsmExpression] construction for [Ring] algebras.
*/
open class AsmExpressionRing<T, A>(override val algebra: A) : AsmExpressionSpace<T, A>(algebra), open class AsmExpressionRing<T, A>(override val algebra: A) : AsmExpressionSpace<T, A>(algebra),
Ring<AsmExpression<T>> where A : Ring<T>, A : NumericAlgebra<T> { Ring<AsmExpression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
override val one: AsmExpression<T> override val one: AsmExpression<T>
get() = const(algebra.one) get() = const(algebra.one)
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> = /**
AsmUnaryOperation(algebra, operation, arg) * Builds an AsmExpression of multiplication of two expressions.
*/
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> = override fun multiply(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b)
operator fun AsmExpression<T>.times(arg: T): AsmExpression<T> = this * const(arg) operator fun AsmExpression<T>.times(arg: T): AsmExpression<T> = this * const(arg)
operator fun T.times(arg: AsmExpression<T>): AsmExpression<T> = arg * this operator fun T.times(arg: AsmExpression<T>): AsmExpression<T> = arg * this
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionSpace>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionSpace>.binaryOperation(operation, left, right)
override fun number(value: Number): AsmExpression<T> = super<AsmExpressionSpace>.number(value)
} }
/**
* A context class for [AsmExpression] construction for [Field] algebras.
*/
open class AsmExpressionField<T, A>(override val algebra: A) : open class AsmExpressionField<T, A>(override val algebra: A) :
AsmExpressionRing<T, A>(algebra), AsmExpressionRing<T, A>(algebra),
Field<AsmExpression<T>> where A : Field<T>, A : NumericAlgebra<T> { Field<AsmExpression<T>> where A : Field<T>, A : NumericAlgebra<T> {
/**
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> = * Builds an AsmExpression of division an expression by another one.
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> = override fun divide(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b)
operator fun AsmExpression<T>.div(arg: T): AsmExpression<T> = this / const(arg) operator fun AsmExpression<T>.div(arg: T): AsmExpression<T> = this / const(arg)
operator fun T.div(arg: AsmExpression<T>): AsmExpression<T> = arg / this operator fun T.div(arg: AsmExpression<T>): AsmExpression<T> = arg / this
}
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionRing>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
super<AsmExpressionRing>.binaryOperation(operation, left, right)
override fun number(value: Number): AsmExpression<T> = super<AsmExpressionRing>.number(value)
}

View File

@ -6,6 +6,15 @@ import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes import org.objectweb.asm.Opcodes
import scientifik.kmath.operations.Algebra import scientifik.kmath.operations.Algebra
/**
* AsmGenerationContext is a structure that abstracts building a class that unwraps [AsmExpression] to plain Java
* expression. This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new
* class.
*
* @param T the type of AsmExpression to unwrap.
* @param algebra the algebra the applied AsmExpressions use.
* @param className the unique class name of new loaded class.
*/
class AsmGenerationContext<T>( class AsmGenerationContext<T>(
classOfT: Class<*>, classOfT: Class<*>,
private val algebra: Algebra<T>, private val algebra: Algebra<T>,
@ -29,8 +38,7 @@ class AsmGenerationContext<T>(
private val invokeArgumentsVar: Int = 1 private val invokeArgumentsVar: Int = 1
private var maxStack: Int = 0 private var maxStack: Int = 0
private val constants: MutableList<Any> = mutableListOf() private val constants: MutableList<Any> = mutableListOf()
private val asmCompiledClassWriter: ClassWriter = private val asmCompiledClassWriter: ClassWriter = ClassWriter(0)
ClassWriter(0)
private val invokeMethodVisitor: MethodVisitor private val invokeMethodVisitor: MethodVisitor
private val invokeL0: Label private val invokeL0: Label
private lateinit var invokeL1: Label private lateinit var invokeL1: Label

View File

@ -28,40 +28,61 @@ internal class FunctionalConstantExpression<T>(val value: T) : Expression<T> {
internal class FunctionalConstProductExpression<T>( internal class FunctionalConstProductExpression<T>(
val context: Space<T>, val context: Space<T>,
val expr: Expression<T>, private val expr: Expression<T>,
val const: Number 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)
} }
/**
* A context class for [Expression] construction.
*/
interface FunctionalExpressionAlgebra<T, A : Algebra<T>> : ExpressionAlgebra<T, Expression<T>> { interface FunctionalExpressionAlgebra<T, A : Algebra<T>> : ExpressionAlgebra<T, Expression<T>> {
/**
* The algebra to provide for Expressions built.
*/
val algebra: A val algebra: A
/**
* Builds an Expression of constant expression which does not depend on arguments.
*/
override fun const(value: T): Expression<T> = FunctionalConstantExpression(value)
/**
* Builds an Expression to access a variable.
*/
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
/**
* Builds an Expression of dynamic call of binary operation [operation] on [left] and [right].
*/
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)
/**
* Builds an Expression of dynamic call of unary operation with name [operation] on [arg].
*/
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)
override fun const(value: T): Expression<T> = FunctionalConstantExpression(value)
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
} }
/**
* A context class for [Expression] construction for [Space] algebras.
*/
open class FunctionalExpressionSpace<T, A>(override val algebra: A) : FunctionalExpressionAlgebra<T, A>, open class FunctionalExpressionSpace<T, A>(override val algebra: A) : FunctionalExpressionAlgebra<T, A>,
Space<Expression<T>> where A : Space<T> { Space<Expression<T>> where A : Space<T> {
override val zero: Expression<T> override val zero: Expression<T>
get() = const(algebra.zero) get() = const(algebra.zero)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> = /**
FunctionalBinaryOperation(algebra, operation, left, right) * Builds an Expression of addition of two another expressions.
*/
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(algebra, SpaceOperations.PLUS_OPERATION, a, b) FunctionalBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
/**
* Builds an Expression of multiplication of expression by number.
*/
override fun multiply(a: Expression<T>, k: Number): Expression<T> = override fun multiply(a: Expression<T>, k: Number): Expression<T> =
FunctionalConstProductExpression(algebra, a, k) FunctionalConstProductExpression(algebra, a, k)
@ -69,6 +90,12 @@ open class FunctionalExpressionSpace<T, A>(override val algebra: A) : Functional
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
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionAlgebra>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionAlgebra>.binaryOperation(operation, left, right)
} }
open class FunctionalExpressionRing<T, A>(override val algebra: A) : FunctionalExpressionSpace<T, A>(algebra), open class FunctionalExpressionRing<T, A>(override val algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
@ -76,34 +103,37 @@ open class FunctionalExpressionRing<T, A>(override val algebra: A) : FunctionalE
override val one: Expression<T> override val one: Expression<T>
get() = const(algebra.one) get() = const(algebra.one)
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> = /**
FunctionalUnaryOperation(algebra, operation, arg) * Builds an Expression of multiplication of two expressions.
*/
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(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(algebra, 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
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionSpace>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionSpace>.binaryOperation(operation, left, right)
} }
open class FunctionalExpressionField<T, A>(override val algebra: A) : open class FunctionalExpressionField<T, A>(override val algebra: A) :
FunctionalExpressionRing<T, A>(algebra), FunctionalExpressionRing<T, A>(algebra),
Field<Expression<T>> where A : Field<T>, A : NumericAlgebra<T> { Field<Expression<T>> where A : Field<T>, A : NumericAlgebra<T> {
/**
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> = * Builds an Expression of division an expression by another one.
FunctionalUnaryOperation(algebra, operation, arg) */
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
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(algebra, 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
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionRing>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionRing>.binaryOperation(operation, left, right)
} }