From cb5234a334d2ffe07403d6ac3b553fd388f54619 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 8 Aug 2020 04:57:20 +0700 Subject: [PATCH] Document AST and expressions API, implement ExtendedField over MST and Expression --- .../kotlin/scientifik/kmath/ast/MST.kt | 47 ++++++++---- .../kotlin/scientifik/kmath/ast/MstAlgebra.kt | 74 +++++++++++++------ .../scientifik/kmath/ast/MstExpression.kt | 65 ++++++++++++---- .../kotlin/scientifik/kmath/ast/parser.kt | 13 ++++ .../scientifik/kmath/expressions/Builders.kt | 8 ++ .../kmath/expressions/Expression.kt | 12 +++ .../FunctionalExpressionAlgebra.kt | 39 ++++++++-- .../scientifik/kmath/streaming/RingBuffer.kt | 2 +- 8 files changed, 202 insertions(+), 58 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt index 46558cbfb..0e8151c04 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -5,42 +5,54 @@ import scientifik.kmath.operations.NumericAlgebra import scientifik.kmath.operations.RealField /** - * A Mathematical Syntax Tree node for mathematical expressions + * A Mathematical Syntax Tree node for mathematical expressions. */ sealed class MST { - /** - * A node containing unparsed string + * A node containing raw string. + * + * @property value the value of this node. */ data class Symbolic(val value: String) : MST() /** - * A node containing a number + * A node containing a numeric value or scalar. + * + * @property value the value of this number. */ data class Numeric(val value: Number) : MST() /** - * A node containing an unary operation + * A node containing an unary operation. + * + * @property operation the identifier of operation. + * @property value the argument of this operation. */ data class Unary(val operation: String, val value: MST) : MST() { - companion object { - const val ABS_OPERATION = "abs" - //TODO add operations - } + companion object } /** - * A node containing binary operation + * A node containing binary operation. + * + * @property operation the identifier operation. + * @property left the left operand. + * @property right the right operand. */ data class Binary(val operation: String, val left: MST, val right: MST) : MST() { companion object } } -//TODO add a function with positional arguments - -//TODO add a function with named arguments +// TODO add a function with named arguments +/** + * Interprets the [MST] node with this [Algebra]. + * + * @receiver the algebra that provides operations. + * @param node the node to evaluate. + * @return the value of expression. + */ fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") @@ -65,4 +77,11 @@ fun Algebra.evaluate(node: MST): T = when (node) { } } -fun MST.compile(algebra: Algebra): T = algebra.evaluate(this) +/** + * Interprets the [MST] node with this [Algebra]. + * + * @receiver the node to evaluate. + * @param algebra the algebra that provides operations. + * @return the value of expression. + */ +fun MST.interpret(algebra: Algebra): T = algebra.evaluate(this) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index 007cf57c4..b47c7cae8 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -2,6 +2,9 @@ package scientifik.kmath.ast import scientifik.kmath.operations.* +/** + * [Algebra] over [MST] nodes. + */ object MstAlgebra : NumericAlgebra { override fun number(value: Number): MST = MST.Numeric(value) @@ -14,17 +17,16 @@ object MstAlgebra : NumericAlgebra { MST.Binary(operation, left, right) } +/** + * [Space] over [MST] nodes. + */ object MstSpace : Space, NumericAlgebra { override val zero: MST = number(0.0) override fun number(value: Number): MST = MstAlgebra.number(value) override fun symbol(value: String): MST = MstAlgebra.symbol(value) - - override fun add(a: MST, b: MST): MST = - binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) - - override fun multiply(a: MST, k: Number): MST = - binaryOperation(RingOperations.TIMES_OPERATION, a, number(k)) + override fun add(a: MST, b: MST): MST = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) + override fun multiply(a: MST, k: Number): MST = binaryOperation(RingOperations.TIMES_OPERATION, a, number(k)) override fun binaryOperation(operation: String, left: MST, right: MST): MST = MstAlgebra.binaryOperation(operation, left, right) @@ -32,41 +34,69 @@ object MstSpace : Space, NumericAlgebra { override fun unaryOperation(operation: String, arg: MST): MST = MstAlgebra.unaryOperation(operation, arg) } +/** + * [Ring] over [MST] nodes. + */ object MstRing : Ring, NumericAlgebra { override val zero: MST = number(0.0) override val one: MST = number(1.0) - override fun number(value: Number): MST = MstAlgebra.number(value) - override fun symbol(value: String): MST = MstAlgebra.symbol(value) - override fun add(a: MST, b: MST): MST = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) + override fun number(value: Number): MST = MstSpace.number(value) + override fun symbol(value: String): MST = MstSpace.symbol(value) + override fun add(a: MST, b: MST): MST = MstSpace.add(a, b) - override fun multiply(a: MST, k: Number): MST = - binaryOperation(RingOperations.TIMES_OPERATION, a, MstSpace.number(k)) + override fun multiply(a: MST, k: Number): MST = MstSpace.multiply(a, k) override fun multiply(a: MST, b: MST): MST = binaryOperation(RingOperations.TIMES_OPERATION, a, b) override fun binaryOperation(operation: String, left: MST, right: MST): MST = - MstAlgebra.binaryOperation(operation, left, right) + MstSpace.binaryOperation(operation, left, right) override fun unaryOperation(operation: String, arg: MST): MST = MstAlgebra.unaryOperation(operation, arg) } +/** + * [Field] over [MST] nodes. + */ object MstField : Field { override val zero: MST = number(0.0) override val one: MST = number(1.0) - override fun symbol(value: String): MST = MstAlgebra.symbol(value) - override fun number(value: Number): MST = MstAlgebra.number(value) - override fun add(a: MST, b: MST): MST = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) - - override fun multiply(a: MST, k: Number): MST = - binaryOperation(RingOperations.TIMES_OPERATION, a, MstSpace.number(k)) - - override fun multiply(a: MST, b: MST): MST = binaryOperation(RingOperations.TIMES_OPERATION, a, b) + override fun symbol(value: String): MST = MstRing.symbol(value) + override fun number(value: Number): MST = MstRing.number(value) + override fun add(a: MST, b: MST): MST = MstRing.add(a, b) + override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) + override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b) override fun binaryOperation(operation: String, left: MST, right: MST): MST = - MstAlgebra.binaryOperation(operation, left, right) + MstRing.binaryOperation(operation, left, right) - override fun unaryOperation(operation: String, arg: MST): MST = MstAlgebra.unaryOperation(operation, arg) + override fun unaryOperation(operation: String, arg: MST): MST = MstRing.unaryOperation(operation, arg) +} + +/** + * [ExtendedField] over [MST] nodes. + */ +object MstExtendedField : ExtendedField { + override val zero: MST = number(0.0) + override val one: MST = number(1.0) + + override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + override fun asin(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ASIN_OPERATION, arg) + override fun acos(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ACOS_OPERATION, arg) + override fun atan(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ATAN_OPERATION, arg) + override fun add(a: MST, b: MST): MST = MstField.add(a, b) + override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k) + override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) + override fun divide(a: MST, b: MST): MST = MstField.divide(a, b) + override fun power(arg: MST, pow: Number): MST = binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) + override fun exp(arg: MST): MST = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + override fun ln(arg: MST): MST = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + + override fun binaryOperation(operation: String, left: MST, right: MST): MST = + MstField.binaryOperation(operation, left, right) + + override fun unaryOperation(operation: String, arg: MST): MST = MstField.unaryOperation(operation, arg) } diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt index 1468c3ad4..59f3f15d8 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt @@ -1,19 +1,16 @@ package scientifik.kmath.ast -import scientifik.kmath.expressions.Expression -import scientifik.kmath.expressions.FunctionalExpressionField -import scientifik.kmath.expressions.FunctionalExpressionRing -import scientifik.kmath.expressions.FunctionalExpressionSpace +import scientifik.kmath.expressions.* import scientifik.kmath.operations.* /** - * The expression evaluates MST on-flight. Should be much faster than functional expression, but slower than ASM-generated expressions. + * The expression evaluates MST on-flight. Should be much faster than functional expression, but slower than + * ASM-generated expressions. + * + * @property algebra the algebra that provides operations. + * @property mst the [MST] node. */ class MstExpression(val algebra: Algebra, val mst: MST) : Expression { - - /** - * Substitute algebra raw value - */ private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { override fun symbol(value: String): T = arguments[value] ?: algebra.symbol(value) override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) @@ -30,26 +27,62 @@ class MstExpression(val algebra: Algebra, val mst: MST) : Expression { override fun invoke(arguments: Map): T = InnerAlgebra(arguments).evaluate(mst) } - +/** + * Builds [MstExpression] over [Algebra]. + */ inline fun , E : Algebra> A.mst( mstAlgebra: E, block: E.() -> MST ): MstExpression = MstExpression(this, mstAlgebra.block()) +/** + * Builds [MstExpression] over [Space]. + */ inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression = MstExpression(this, MstSpace.block()) +/** + * Builds [MstExpression] over [Ring]. + */ inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression = MstExpression(this, MstRing.block()) +/** + * Builds [MstExpression] over [Field]. + */ inline fun Field.mstInField(block: MstField.() -> MST): MstExpression = MstExpression(this, MstField.block()) -inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression = - algebra.mstInSpace(block) +/** + * Builds [MstExpression] over [ExtendedField]. + */ +inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression = + MstExpression(this, MstExtendedField.block()) -inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression = - algebra.mstInRing(block) +/** + * Builds [MstExpression] over [FunctionalExpressionSpace]. + */ +inline fun > FunctionalExpressionSpace.mstInSpace( + block: MstSpace.() -> MST +): MstExpression = algebra.mstInSpace(block) -inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression = - algebra.mstInField(block) \ No newline at end of file +/** + * Builds [MstExpression] over [FunctionalExpressionRing]. + */ +inline fun > FunctionalExpressionRing.mstInRing( + block: MstRing.() -> MST +): MstExpression = algebra.mstInRing(block) + +/** + * Builds [MstExpression] over [FunctionalExpressionField]. + */ +inline fun > FunctionalExpressionField.mstInField( + block: MstField.() -> MST +): MstExpression = algebra.mstInField(block) + +/** + * Builds [MstExpression] over [FunctionalExpressionExtendedField]. + */ +inline fun > FunctionalExpressionExtendedField.mstInExtendedField( + block: MstExtendedField.() -> MST +): MstExpression = algebra.mstInExtendedField(block) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt index 11797d79f..cba335a8d 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt @@ -80,5 +80,18 @@ object ArithmeticsEvaluator : Grammar() { override val rootParser: Parser by subSumChain } +/** + * Tries to parse the string into [MST]. + * + * @receiver the string to parse. + * @return the [MST] node. + */ fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) + +/** + * Parses the string into [MST]. + * + * @receiver the string to parse. + * @return the [MST] node. + */ fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) 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 834ef9e24..8cd6e28f8 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt @@ -1,5 +1,6 @@ package scientifik.kmath.expressions +import scientifik.kmath.operations.ExtendedField import scientifik.kmath.operations.Field import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space @@ -21,3 +22,10 @@ fun Ring.ringExpression(block: FunctionalExpressionRing>.() -> */ fun Field.fieldExpression(block: FunctionalExpressionField>.() -> Expression): Expression = FunctionalExpressionField(this).run(block) + +/** + * Creates a functional expression with this [ExtendedField]. + */ +fun ExtendedField.fieldExpression( + block: FunctionalExpressionExtendedField>.() -> Expression +): Expression = FunctionalExpressionExtendedField(this).run(block) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt index b21a414f5..380822f78 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt @@ -6,6 +6,12 @@ import scientifik.kmath.operations.Algebra * An elementary function that could be invoked on a map of arguments */ interface Expression { + /** + * Calls this expression from arguments. + * + * @param arguments the map of arguments. + * @return the value. + */ operator fun invoke(arguments: Map): T companion object @@ -19,6 +25,12 @@ fun Algebra.expression(block: Algebra.(arguments: Map) -> T override fun invoke(arguments: Map): T = block(arguments) } +/** + * Calls this expression from arguments. + * + * @param pairs the pair of arguments' names to values. + * @return the value. + */ operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt index 5a8a10717..dd5fb572a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -40,7 +40,6 @@ internal class FunctionalConstProductExpression( * @param algebra The algebra to provide for Expressions built. */ abstract class FunctionalExpressionAlgebra>(val algebra: A) : ExpressionAlgebra> { - /** * Builds an Expression of constant expression which does not depend on arguments. */ @@ -69,14 +68,13 @@ abstract class FunctionalExpressionAlgebra>(val algebra: A) : */ open class FunctionalExpressionSpace>(algebra: A) : FunctionalExpressionAlgebra(algebra), Space> { - override val zero: Expression get() = const(algebra.zero) /** * Builds an Expression of addition of two another expressions. */ override fun add(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) + binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) /** * Builds an Expression of multiplication of expression by number. @@ -105,7 +103,7 @@ open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpac * Builds an Expression of multiplication of two expressions. */ override fun multiply(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) + binaryOperation(RingOperations.TIMES_OPERATION, a, b) operator fun Expression.times(arg: T): Expression = this * const(arg) operator fun T.times(arg: Expression): Expression = arg * this @@ -124,7 +122,7 @@ open class FunctionalExpressionField(algebra: A) : * Builds an Expression of division an expression by another one. */ override fun divide(a: Expression, b: Expression): Expression = - FunctionalBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) + binaryOperation(FieldOperations.DIV_OPERATION, a, b) operator fun Expression.div(arg: T): Expression = this / const(arg) operator fun T.div(arg: Expression): Expression = arg / this @@ -136,6 +134,34 @@ open class FunctionalExpressionField(algebra: A) : super.binaryOperation(operation, left, right) } +open class FunctionalExpressionExtendedField(algebra: A) : + FunctionalExpressionField(algebra), + ExtendedField> where A : ExtendedField, A : NumericAlgebra { + override fun sin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + override fun cos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + + override fun asin(arg: Expression): Expression = + unaryOperation(InverseTrigonometricOperations.ASIN_OPERATION, arg) + + override fun acos(arg: Expression): Expression = + unaryOperation(InverseTrigonometricOperations.ACOS_OPERATION, arg) + + override fun atan(arg: Expression): Expression = + unaryOperation(InverseTrigonometricOperations.ATAN_OPERATION, arg) + + override fun power(arg: Expression, pow: Number): Expression = + binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) + + override fun exp(arg: Expression): Expression = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + + override fun unaryOperation(operation: String, arg: Expression): Expression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + super.binaryOperation(operation, left, right) +} + inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = FunctionalExpressionSpace(this).block() @@ -144,3 +170,6 @@ inline fun > A.expressionInRing(block: FunctionalExpressionRing> A.expressionInField(block: FunctionalExpressionField.() -> Expression): Expression = FunctionalExpressionField(this).block() + +inline fun > A.expressionInExtendedField(block: FunctionalExpressionExtendedField.() -> Expression): Expression = + FunctionalExpressionExtendedField(this).block() diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt index 6b99e34ff..fca9ffb9f 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt @@ -11,7 +11,7 @@ import kotlin.reflect.KClass * Thread-safe ring buffer */ @Suppress("UNCHECKED_CAST") -internal class RingBuffer( +class RingBuffer( private val buffer: MutableBuffer, private var startIndex: Int = 0, size: Int = 0