From 0507bfcc24ada2bdc52ad5ceadaafd4d7f0d0ccb Mon Sep 17 00:00:00 2001 From: darksnake Date: Thu, 11 Jun 2020 09:46:42 +0300 Subject: [PATCH] Expression simplification --- .../kmath/expressions/Expression.kt | 9 ----- .../kmath/expressions/SyntaxTreeNode.kt | 32 ++++++++++++++--- .../scientifik/kmath/operations/Algebra.kt | 36 ++++++++++++++++--- 3 files changed, 60 insertions(+), 17 deletions(-) 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 73745f78f..aba7357e8 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt @@ -24,13 +24,4 @@ interface ExpressionContext : Algebra { * A constant expression which does not depend on arguments */ fun const(value: T): E -} - -fun ExpressionContext.produce(node: SyntaxTreeNode): E { - return when (node) { - is NumberNode -> error("Single number nodes are not supported") - is SingularNode -> variable(node.value) - is UnaryNode -> unaryOperation(node.operation, produce(node.value)) - is BinaryNode -> binaryOperation(node.operation, produce(node.left), produce(node.right)) - } } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/SyntaxTreeNode.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/SyntaxTreeNode.kt index b4038f680..e56165aad 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/SyntaxTreeNode.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/SyntaxTreeNode.kt @@ -1,11 +1,25 @@ package scientifik.kmath.expressions +import scientifik.kmath.operations.NumericAlgebra + +/** + * A syntax tree node for mathematical expressions + */ sealed class SyntaxTreeNode +/** + * A node containing unparsed string + */ data class SingularNode(val value: String) : SyntaxTreeNode() +/** + * A node containing a number + */ data class NumberNode(val value: Number) : SyntaxTreeNode() +/** + * A node containing an unary operation + */ data class UnaryNode(val operation: String, val value: SyntaxTreeNode) : SyntaxTreeNode() { companion object { const val ABS_OPERATION = "abs" @@ -17,12 +31,22 @@ data class UnaryNode(val operation: String, val value: SyntaxTreeNode) : SyntaxT } } +/** + * A node containing binary operation + */ data class BinaryNode(val operation: String, val left: SyntaxTreeNode, val right: SyntaxTreeNode) : SyntaxTreeNode() { - companion object { - //TODO add operations - } + companion object } //TODO add a function with positional arguments -//TODO add a function with named arguments \ No newline at end of file +//TODO add a function with named arguments + +fun NumericAlgebra.compile(node: SyntaxTreeNode): T{ + return when (node) { + is NumberNode -> number(node.value) + is SingularNode -> raw(node.value) + is UnaryNode -> unaryOperation(node.operation, compile(node.value)) + is BinaryNode -> binaryOperation(node.operation, compile(node.left), compile(node.right)) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt index b3282e5f3..c9fbc1c8b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt @@ -7,10 +7,35 @@ annotation class KMathContext * Marker interface for any algebra */ interface Algebra { + /** + * Wrap raw string or variable + */ + fun raw(value: String): T = error("Wrapping of '$value' is not supported in $this") + + /** + * Dynamic call of unary operation with name [operation] on [arg] + */ fun unaryOperation(operation: String, arg: T): T + + /** + * Dynamic call of binary operation [operation] on [left] and [right] + */ fun binaryOperation(operation: String, left: T, right: T): T } +/** + * An algebra with numeric representation of members + */ +interface NumericAlgebra : Algebra { + /** + * Wrap a number + */ + fun number(value: Number): T +} + +/** + * Call a block with an [Algebra] as receiver + */ inline operator fun , R> A.invoke(block: A.() -> R): R = run(block) /** @@ -87,7 +112,7 @@ interface RingOperations : SpaceOperations { else -> super.binaryOperation(operation, left, right) } - companion object{ + companion object { const val TIMES_OPERATION = "*" } } @@ -95,13 +120,16 @@ interface RingOperations : SpaceOperations { /** * The same as {@link Space} but with additional multiplication operation */ -interface Ring : Space, RingOperations { +interface Ring : Space, RingOperations, NumericAlgebra { /** * neutral operation for multiplication */ val one: T -// operator fun T.plus(b: Number) = this.plus(b * one) + override fun number(value: Number): T = one * value.toDouble() + + // those operators are blocked by type conflict in RealField + // operator fun T.plus(b: Number) = this.plus(b * one) // operator fun Number.plus(b: T) = b + this // // operator fun T.minus(b: Number) = this.minus(b * one) @@ -121,7 +149,7 @@ interface FieldOperations : RingOperations { else -> super.binaryOperation(operation, left, right) } - companion object{ + companion object { const val DIV_OPERATION = "/" } }