Merge branch 'dev' into feature/tensor-algebra

This commit is contained in:
Roland Grinis 2021-04-30 09:20:26 +01:00
commit e371a4a6db
18 changed files with 265 additions and 104 deletions

View File

@ -50,7 +50,7 @@ For example, the following builder:
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
```
leads to generation of bytecode, which can be decompiled to the following Java class:
... leads to generation of bytecode, which can be decompiled to the following Java class:
```java
package space.kscience.kmath.asm.generated;
@ -97,6 +97,7 @@ var executable = function (constants, arguments) {
};
```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
import space.kscience.kmath.wasm.*
@ -104,7 +105,7 @@ import space.kscience.kmath.wasm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
```
An example of emitted WASM IR in the form of WAT:
An example of emitted Wasm IR in the form of WAT:
```lisp
(func $executable (param $0 f64) (result f64)

View File

@ -18,6 +18,10 @@ kotlin.js {
}
kotlin.sourceSets {
filter { it.name.contains("test", true) }
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
.forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") }
commonMain {
dependencies {
api("com.github.h0tk3y.betterParse:better-parse:0.4.2")
@ -54,7 +58,7 @@ tasks.dokkaHtml {
}
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
feature(

View File

@ -19,7 +19,7 @@ For example, the following builder:
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
```
leads to generation of bytecode, which can be decompiled to the following Java class:
... leads to generation of bytecode, which can be decompiled to the following Java class:
```java
package space.kscience.kmath.asm.generated;
@ -66,6 +66,7 @@ var executable = function (constants, arguments) {
};
```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
import space.kscience.kmath.wasm.*
@ -73,7 +74,7 @@ import space.kscience.kmath.wasm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
```
An example of emitted WASM IR in the form of WAT:
An example of emitted Wasm IR in the form of WAT:
```lisp
(func \$executable (param \$0 f64) (result f64)

View File

@ -29,7 +29,6 @@ import space.kscience.kmath.operations.RingOperations
* @author Iaroslav Postovalov
*/
public object ArithmeticsEvaluator : Grammar<MST>() {
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex())
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
private val lpar: Token by literalToken("(")

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* [SyntaxRenderer] implementation for LaTeX.
*
@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object LatexSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
fun render(syntax: MathSyntax) = render(syntax, output)

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* [SyntaxRenderer] implementation for MathML.
*
@ -12,9 +14,10 @@ package space.kscience.kmath.ast.rendering
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object MathMLSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable) {
output.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>")
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
render0(node, output)
output.append("</mrow></math>")
}

View File

@ -6,12 +6,14 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Renders [MST] to [MathSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun interface MathRenderer {
/**
* Renders [MST] to [MathSyntax].
@ -25,6 +27,7 @@ public fun interface MathRenderer {
* @property features The applied features.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
public override fun render(mst: MST): MathSyntax {
for (feature in features) feature.render(this, mst)?.let { return it }
@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List<RenderFeature>)
* @property stages The applied stages.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public open class FeaturedMathRendererWithPostProcess(
features: List<RenderFeature>,
public val stages: List<PostProcessStage>,

View File

@ -5,11 +5,14 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Mathematical typography syntax node.
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public sealed class MathSyntax {
/**
* The parent node of this syntax node.
@ -22,6 +25,7 @@ public sealed class MathSyntax {
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public sealed class TerminalSyntax : MathSyntax()
/**
@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax()
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public sealed class OperationSyntax : MathSyntax() {
/**
* The operation token.
@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() {
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public sealed class UnarySyntax : OperationSyntax() {
/**
* The operand of this node.
@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() {
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public sealed class BinarySyntax : OperationSyntax() {
/**
* The left-hand side operand.
@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() {
* @property string The digits of number.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class NumberSyntax(public var string: String) : TerminalSyntax()
/**
@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax()
* @property string The symbol.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class SymbolSyntax(public var string: String) : TerminalSyntax()
/**
@ -89,6 +98,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax()
* @see UnaryOperatorSyntax
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class OperatorNameSyntax(public var name: String) : TerminalSyntax()
/**
@ -97,6 +107,7 @@ public data class OperatorNameSyntax(public var name: String) : TerminalSyntax()
* @property kind The kind of symbol.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() {
/**
* The kind of symbol.
@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax()
* @property parentheses Whether the operand should be wrapped with parentheses.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class OperandSyntax(
public val operand: MathSyntax,
public var parentheses: Boolean,
@ -136,6 +148,7 @@ public data class OperandSyntax(
* @property prefix The prefix.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class UnaryOperatorSyntax(
public override val operation: String,
public var prefix: MathSyntax,
@ -151,6 +164,7 @@ public data class UnaryOperatorSyntax(
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class UnaryPlusSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
@ -165,6 +179,7 @@ public data class UnaryPlusSyntax(
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class UnaryMinusSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
@ -180,6 +195,7 @@ public data class UnaryMinusSyntax(
* @property operand The radicand.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class RadicalSyntax(
public override val operation: String,
public override val operand: MathSyntax,
@ -197,6 +213,7 @@ public data class RadicalSyntax(
* (*e<sup>x</sup>*).
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class ExponentSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
@ -214,6 +231,7 @@ public data class ExponentSyntax(
* @property right The superscript.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class SuperscriptSyntax(
public override val operation: String,
public override val left: MathSyntax,
@ -232,6 +250,7 @@ public data class SuperscriptSyntax(
* @property right The subscript.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class SubscriptSyntax(
public override val operation: String,
public override val left: MathSyntax,
@ -249,6 +268,7 @@ public data class SubscriptSyntax(
* @property prefix The prefix.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class BinaryOperatorSyntax(
public override val operation: String,
public var prefix: MathSyntax,
@ -268,6 +288,7 @@ public data class BinaryOperatorSyntax(
* @param right The addend.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class BinaryPlusSyntax(
public override val operation: String,
public override val left: OperandSyntax,
@ -286,6 +307,7 @@ public data class BinaryPlusSyntax(
* @param right The subtrahend.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class BinaryMinusSyntax(
public override val operation: String,
public override val left: OperandSyntax,
@ -304,6 +326,7 @@ public data class BinaryMinusSyntax(
* @property right The denominator.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class FractionSyntax(
public override val operation: String,
public override val left: MathSyntax,
@ -322,6 +345,7 @@ public data class FractionSyntax(
* @property right The radicand.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class RadicalWithIndexSyntax(
public override val operation: String,
public override val left: MathSyntax,
@ -341,6 +365,7 @@ public data class RadicalWithIndexSyntax(
* @property times whether the times (&times;) symbol should be used.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public data class MultiplicationSyntax(
public override val operation: String,
public override val left: OperandSyntax,

View File

@ -5,12 +5,15 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
* involve traversal of MathSyntax with handling each its subtype.
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun interface SyntaxRenderer {
/**
* Renders the [MathSyntax] to [output].
@ -23,6 +26,7 @@ public fun interface SyntaxRenderer {
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String {
val sb = StringBuilder()
render(node, sb)

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
import kotlin.reflect.KClass
@ -15,11 +16,12 @@ import kotlin.reflect.KClass
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object PrintSymbolic : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Symbolic) return null
return SymbolSyntax(string = node.value)
}
public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
if (node !is MST.Symbolic) null
else
SymbolSyntax(string = node.value)
}
/**
@ -27,25 +29,25 @@ public object PrintSymbolic : RenderFeature {
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object PrintNumeric : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric) return null
return NumberSyntax(string = node.value.toString())
}
public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
null
else
NumberSyntax(string = node.value.toString())
}
private fun printSignedNumberString(s: String): MathSyntax {
if (s.startsWith('-'))
return UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax(
operand = NumberSyntax(string = s.removePrefix("-")),
parentheses = true,
),
)
return NumberSyntax(string = s)
}
@UnstableKMathAPI
private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-'))
UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax(
operand = NumberSyntax(string = s.removePrefix("-")),
parentheses = true,
),
)
else
NumberSyntax(string = s)
/**
* Special printing for numeric types which are printed in form of
@ -53,9 +55,11 @@ private fun printSignedNumberString(s: String): MathSyntax {
*
* @property types The suitable types.
*/
@UnstableKMathAPI
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric || node.value::class !in types) return null
val toString = when (val v = node.value) {
is Float -> v.multiplatformToString()
is Double -> v.multiplatformToString()
@ -110,11 +114,13 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
*
* @property types The suitable types.
*/
@UnstableKMathAPI
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric || node.value::class !in types) return null
return printSignedNumberString(node.value.toString())
}
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Numeric || node.value::class !in types)
null
else
printSignedNumberString(node.value.toString())
public companion object {
/**
@ -130,11 +136,13 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
*
* @property symbols The allowed symbols.
*/
@UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Symbolic || node.value !in symbols) return null
return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
}
public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
if (node !is MST.Symbolic || node.value !in symbols)
null
else
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
public companion object {
/**
@ -150,16 +158,18 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
*
* @param operations the allowed operations. If `null`, any operation is accepted.
*/
@UnstableKMathAPI
public abstract class Unary(public val operations: Collection<String>?) : RenderFeature {
/**
* The actual render function.
* The actual render function specialized for [MST.Unary].
*/
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax?
protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax?
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Unary || operations != null && node.operation !in operations) return null
return render0(renderer, node)
}
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Unary || operations != null && node.operation !in operations)
null
else
renderUnary(renderer, node)
}
/**
@ -168,164 +178,258 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
*
* @property operations the allowed operations. If `null`, any operation is accepted.
*/
@UnstableKMathAPI
public abstract class Binary(public val operations: Collection<String>?) : RenderFeature {
/**
* The actual render function.
* The actual render function specialized for [MST.Binary].
*/
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax?
protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax?
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Binary || operations != null && node.operation !in operations) return null
return render0(renderer, node)
return renderBinary(renderer, node)
}
}
/**
* Handles binary nodes by producing [BinaryPlusSyntax].
*/
@UnstableKMathAPI
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true),
)
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
BinaryPlusSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
*/
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION))
}
}
/**
* Handles binary nodes by producing [BinaryMinusSyntax].
*/
@UnstableKMathAPI
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
)
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
BinaryMinusSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
*/
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION))
}
}
/**
* Handles unary nodes by producing [UnaryPlusSyntax].
*/
@UnstableKMathAPI
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
*/
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION))
}
}
/**
* Handles binary nodes by producing [UnaryMinusSyntax].
*/
@UnstableKMathAPI
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
*/
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION))
}
}
/**
* Handles binary nodes by producing [FractionSyntax].
*/
@UnstableKMathAPI
public class Fraction(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
operation = node.operation,
left = parent.render(node.left),
right = parent.render(node.right),
)
public companion object {
/**
* The default instance configured with [FieldOperations.DIV_OPERATION].
*/
public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION))
}
}
/**
* Handles binary nodes by producing [BinaryOperatorSyntax].
*/
@UnstableKMathAPI
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation),
left = parent.render(node.left),
right = parent.render(node.right),
)
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
BinaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation),
left = parent.render(node.left),
right = parent.render(node.right),
)
public companion object {
/**
* The default instance configured with `null`.
*/
public val Default: BinaryOperator = BinaryOperator(null)
}
}
/**
* Handles unary nodes by producing [UnaryOperatorSyntax].
*/
@UnstableKMathAPI
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(node.operation),
operand = OperandSyntax(parent.render(node.value), true),
)
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(node.operation),
operand = OperandSyntax(parent.render(node.value), true),
)
public companion object {
/**
* The default instance configured with `null`.
*/
public val Default: UnaryOperator = UnaryOperator(null)
}
}
/**
* Handles binary nodes by producing [SuperscriptSyntax].
*/
@UnstableKMathAPI
public class Power(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true),
)
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
SuperscriptSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true),
)
public companion object {
/**
* The default instance configured with [PowerOperations.POW_OPERATION].
*/
public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION))
}
}
/**
* Handles binary nodes by producing [RadicalSyntax] with no index.
*/
@UnstableKMathAPI
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax =
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
public companion object {
/**
* The default instance configured with [PowerOperations.SQRT_OPERATION].
*/
public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION))
}
}
/**
* Handles unary nodes by producing [ExponentSyntax].
*/
@UnstableKMathAPI
public class Exponent(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
useOperatorForm = true,
)
public companion object {
/**
* The default instance configured with [ExponentialOperations.EXP_OPERATION].
*/
public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION))
}
}
/**
* Handles binary nodes by producing [MultiplicationSyntax].
*/
@UnstableKMathAPI
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
times = true,
)
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax =
MultiplicationSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
times = true,
)
public companion object {
public val Default: Multiplication = Multiplication(setOf(
RingOperations.TIMES_OPERATION,
))
/**
* The default instance configured with [RingOperations.TIMES_OPERATION].
*/
public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION))
}
}
/**
* Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin<sup>-1</sup>*) with removing the `a`
* prefix of operation ID.
*/
@UnstableKMathAPI
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax(
operation = node.operation,
prefix = SuperscriptSyntax(
operation = PowerOperations.POW_OPERATION,
left = OperatorNameSyntax(name = node.operation.removePrefix("a")),
right = UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true),
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = SuperscriptSyntax(
operation = PowerOperations.POW_OPERATION,
left = OperatorNameSyntax(name = node.operation.removePrefix("a")),
right = UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true),
),
),
),
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [TrigonometricOperations.ACOS_OPERATION],
* [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION],
* [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and
* [ExponentialOperations.ATANH_OPERATION].
*/
public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf(
TrigonometricOperations.ACOS_OPERATION,
TrigonometricOperations.ASIN_OPERATION,

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.PowerOperations
@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
public override fun perform(node: MathSyntax): Unit = when (node) {
is NumberSyntax -> Unit
@ -88,6 +90,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
private fun perform0(node: MathSyntax): Boolean {
return when (node) {
@ -129,6 +132,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
* @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
FeaturedMathRendererWithPostProcess.PostProcessStage {
public override fun perform(node: MathSyntax): Unit = when (node) {

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.ast
import space.kscience.kmath.ast.parseMath
import space.kscience.kmath.expressions.evaluate
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test

View File

@ -30,17 +30,17 @@ internal object TestUtils {
)
internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = mathML(mst),
)
internal fun testMathML(expression: String, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = mathML(expression.parseMath()),
)
internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression),
)
}

View File

@ -3,7 +3,8 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("INTERFACE_WITH_SUPERCLASS",
@file:Suppress(
"INTERFACE_WITH_SUPERCLASS",
"OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS",

View File

@ -26,7 +26,7 @@ internal sealed class WasmBuilder<T>(
val keys: MutableList<String> = mutableListOf()
lateinit var ctx: BinaryenModule
open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef {
open fun visitSymbolic(mst: Symbolic): ExpressionRef {
try {
algebra.bindSymbol(mst.value)
} catch (ignored: Throwable) {

View File

@ -10,6 +10,7 @@ import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.wasm.internal.DoubleWasmBuilder
@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun DoubleField.expression(mst: MST): Expression<Double> =
DoubleWasmBuilder(mst).instance
@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression<Double> =
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun IntRing.expression(mst: MST): Expression<Int> =
IntWasmBuilder(mst).instance
@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression<Int> =
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileWith(algebra)
@ -44,6 +48,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileW
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
compileToExpression(algebra).invoke(arguments)
@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int =
compileToExpression(algebra)(*arguments)
@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): I
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = compileWith(algebra)
@ -69,6 +76,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = c
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
compileToExpression(algebra).invoke(arguments)
@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Do
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
compileToExpression(algebra).invoke(*arguments)

View File

@ -342,8 +342,8 @@ internal class AsmBuilder<T>(
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
/**
* ASM Type for [kscience.kmath.expressions.Symbol].
* ASM Type for [space.kscience.kmath.misc.Symbol].
*/
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") }
}
}

View File

@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
*
* @author Iaroslav Postovalov
*/
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
internal fun MethodVisitor.label(): Label = Label().also(::visitLabel)
/**
* Creates a class name for [Expression] subclassed to implement [mst] provided.