From c64a89c6b6296517d7c7b9690e7ae319ae54fcd8 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 27 Jul 2020 19:27:59 +0700 Subject: [PATCH] Implement power as binary operation with unchecked cast, add tests on parser precedence --- .../kotlin/scientifik/kmath/ast/MST.kt | 8 ++--- .../kmath/ast/ParserPrecedenceTest.kt | 36 +++++++++++++++++++ .../kmath/operations/NumberAlgebra.kt | 11 ++++-- 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt 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 e87df882f..1127c18aa 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -2,7 +2,6 @@ package scientifik.kmath.ast import scientifik.kmath.operations.Algebra import scientifik.kmath.operations.NumericAlgebra -import scientifik.kmath.operations.RealField /** * A Mathematical Syntax Tree node for mathematical expressions @@ -49,12 +48,11 @@ fun Algebra.evaluate(node: MST): T = when (node) { is MST.Binary -> when { this !is NumericAlgebra -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right)) node.left is MST.Numeric && node.right is MST.Numeric -> { - val number = RealField.binaryOperation( + binaryOperation( node.operation, - node.left.value.toDouble(), - node.right.value.toDouble() + number(node.left.value), + number(node.right.value) ) - number(number) } node.left is MST.Numeric -> leftSideNumberOperation(node.operation, node.left.value, evaluate(node.right)) node.right is MST.Numeric -> rightSideNumberOperation(node.operation, evaluate(node.left), node.right.value) diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt new file mode 100644 index 000000000..9bdbb12c9 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt @@ -0,0 +1,36 @@ +package scietifik.kmath.ast + +import scientifik.kmath.ast.evaluate +import scientifik.kmath.ast.parseMath +import scientifik.kmath.operations.Field +import scientifik.kmath.operations.RealField +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class ParserPrecedenceTest { + private val f: Field = RealField + + @Test + fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) + + @Test + fun test2(): Unit = assertEquals(6.0, f.evaluate("2+2*2".parseMath())) + + @Test + fun test3(): Unit = assertEquals(10.0, f.evaluate("2^3+2".parseMath())) + + @Test + fun test4(): Unit = assertEquals(10.0, f.evaluate("2+2^3".parseMath())) + + @Test + fun test5(): Unit = assertEquals(16.0, f.evaluate("2^3*2".parseMath())) + + @Test + fun test6(): Unit = assertEquals(16.0, f.evaluate("2*2^3".parseMath())) + + @Test + fun test7(): Unit = assertEquals(18.0, f.evaluate("2+2^3*2".parseMath())) + + @Test + fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath())) +} diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt index 953c5a112..ca5fa68f0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt @@ -34,6 +34,13 @@ interface ExtendedField : ExtendedFieldOperations, Field { } } +interface NumberExtendedField : ExtendedField { + override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { + PowerOperations.POW_OPERATION -> power(left, right as Number) + else -> super.binaryOperation(operation, left, right) + } +} + /** * Real field element wrapping double. * @@ -53,7 +60,7 @@ inline class Real(val value: Double) : FieldElement { * A field for double without boxing. Does not produce appropriate field element */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RealField : ExtendedField, Norm { +object RealField : NumberExtendedField, Norm { override val zero: Double = 0.0 override inline fun add(a: Double, b: Double) = a + b override inline fun multiply(a: Double, b: Double) = a * b @@ -88,7 +95,7 @@ object RealField : ExtendedField, Norm { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object FloatField : ExtendedField, Norm { +object FloatField : NumberExtendedField, Norm { override val zero: Float = 0f override inline fun add(a: Float, b: Float) = a + b override inline fun multiply(a: Float, b: Float) = a * b