Implement power as binary operation with unchecked cast, add tests on parser precedence

This commit is contained in:
Iaroslav 2020-07-27 19:27:59 +07:00
parent 1ebd362696
commit c64a89c6b6
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
3 changed files with 48 additions and 7 deletions

View File

@ -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 <T> Algebra<T>.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)

View File

@ -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<Double> = 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()))
}

View File

@ -34,6 +34,13 @@ interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
}
}
interface NumberExtendedField<T> : ExtendedField<T> {
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<Double, Real, RealField> {
* 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<Double>, Norm<Double, Double> {
object RealField : NumberExtendedField<Double>, Norm<Double, Double> {
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<Double>, Norm<Double, Double> {
}
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object FloatField : ExtendedField<Float>, Norm<Float, Float> {
object FloatField : NumberExtendedField<Float>, Norm<Float, Float> {
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