forked from kscience/kmath
Implement power as binary operation with unchecked cast, add tests on parser precedence
This commit is contained in:
parent
1ebd362696
commit
c64a89c6b6
@ -2,7 +2,6 @@ package scientifik.kmath.ast
|
|||||||
|
|
||||||
import scientifik.kmath.operations.Algebra
|
import scientifik.kmath.operations.Algebra
|
||||||
import scientifik.kmath.operations.NumericAlgebra
|
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
|
||||||
@ -49,12 +48,11 @@ fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
|||||||
is MST.Binary -> when {
|
is MST.Binary -> when {
|
||||||
this !is NumericAlgebra -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right))
|
this !is NumericAlgebra -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right))
|
||||||
node.left is MST.Numeric && node.right is MST.Numeric -> {
|
node.left is MST.Numeric && node.right is MST.Numeric -> {
|
||||||
val number = RealField.binaryOperation(
|
binaryOperation(
|
||||||
node.operation,
|
node.operation,
|
||||||
node.left.value.toDouble(),
|
number(node.left.value),
|
||||||
node.right.value.toDouble()
|
number(node.right.value)
|
||||||
)
|
)
|
||||||
number(number)
|
|
||||||
}
|
}
|
||||||
node.left is MST.Numeric -> leftSideNumberOperation(node.operation, node.left.value, evaluate(node.right))
|
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)
|
node.right is MST.Numeric -> rightSideNumberOperation(node.operation, evaluate(node.left), node.right.value)
|
||||||
|
@ -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()))
|
||||||
|
}
|
@ -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.
|
* 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
|
* A field for double without boxing. Does not produce appropriate field element
|
||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@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 val zero: Double = 0.0
|
||||||
override inline fun add(a: Double, b: Double) = a + b
|
override inline fun add(a: Double, b: Double) = a + b
|
||||||
override inline fun multiply(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")
|
@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 val zero: Float = 0f
|
||||||
override inline fun add(a: Float, b: Float) = a + b
|
override inline fun add(a: Float, b: Float) = a + b
|
||||||
override inline fun multiply(a: Float, b: Float) = a * b
|
override inline fun multiply(a: Float, b: Float) = a * b
|
||||||
|
Loading…
Reference in New Issue
Block a user