From 488f5f00087ba45ea137a1ee527468cf4dd40dbc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 8 Apr 2021 00:52:27 +0700 Subject: [PATCH] Redesign exponential function rendering --- .../ast/rendering/LatexSyntaxRenderer.kt | 9 + .../ast/rendering/MathMLSyntaxRenderer.kt | 13 + .../kmath/ast/rendering/MathRenderer.kt | 3 +- .../kmath/ast/rendering/MathSyntax.kt | 18 ++ .../kscience/kmath/ast/rendering/features.kt | 24 +- .../ast/rendering/multiplatformToString.kt | 9 + .../kscience/kmath/ast/rendering/stages.kt | 293 ++++++++++-------- .../kmath/ast/ParserPrecedenceTest.kt | 2 +- .../kmath/ast/ParserTest.kt | 3 +- .../kmath/ast/rendering/TestFeatures.kt | 16 + .../kmath/ast/rendering/TestLatex.kt | 0 .../kmath/ast/rendering/TestMathML.kt | 0 .../kmath/ast/rendering/TestStages.kt | 7 + .../kmath/ast/rendering/TestUtils.kt | 0 .../ast/rendering/multiplatformToString.kt | 18 ++ .../ast/rendering/multiplatformToString.kt | 9 + 16 files changed, 283 insertions(+), 141 deletions(-) create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserPrecedenceTest.kt (97%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserTest.kt (95%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestFeatures.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestLatex.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestMathML.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestStages.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestUtils.kt (100%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt create mode 100644 kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 34230f3c8..1c82bd6e7 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -71,6 +71,15 @@ public object LatexSyntaxRenderer : SyntaxRenderer { append('}') } + is ExponentSyntax -> if (node.useOperatorForm) { + append("\\operatorname{exp}\\,") + render(node.operand) + } else { + append("e^{") + render(node.operand) + append('}') + } + is SuperscriptSyntax -> { render(node.left) append("^{") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index f7487a356..decd4ba46 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -82,6 +82,19 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { is RadicalSyntax -> tag("msqrt") { render(node.operand) } + is ExponentSyntax -> if (node.useOperatorForm) { + tag("mo") { append("exp") } + tag("mspace", "width" to "0.167em") + render(node.operand) + } else { + tag("msup") { + tag("mrow") { + tag("mi") { append("e") } + } + tag("mrow") { render(node.operand) } + } + } + is SuperscriptSyntax -> tag("msup") { tag("mrow") { render(node.left) } tag("mrow") { render(node.right) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 891e8f05b..9df2c54dd 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -83,7 +83,7 @@ public open class FeaturedMathRendererWithPostProcess( Fraction.Default, Power.Default, SquareRoot.Default, - Exponential.Default, + Exponent.Default, InverseTrigonometricOperations.Default, // Fallback option for unknown operations - printing them as operator @@ -100,6 +100,7 @@ public open class FeaturedMathRendererWithPostProcess( PrintSymbolic, ), listOf( + BetterExponent, SimplifyParentheses.Default, BetterMultiplication, ), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 069e56c71..6a46bf535 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -189,6 +189,24 @@ public data class RadicalSyntax( } } +/** + * Represents exponential function. + * + * @property operand The argument of function. + * @property useOperatorForm `true` if operator form is used (*exp (x)*), `false` if exponentiation form is used + * (*ex*). + * @author Iaroslav Postovalov + */ +public data class ExponentSyntax( + public override val operation: String, + public override val operand: OperandSyntax, + public var useOperatorForm: Boolean, +) : UnarySyntax() { + init { + operand.parent = this + } +} + /** * Represents a syntax node with superscript (usually, for exponentiation). * diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 5d6c7bb0a..c09282bb6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -56,10 +56,14 @@ private fun printSignedNumberString(s: String): MathSyntax { public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null - val toString = node.value.toString().removeSuffix(".0") + val toString = when (val v = node.value) { + is Float -> v.multiplatformToString() + is Double -> v.multiplatformToString() + else -> v.toString() + }.removeSuffix(".0") - if ('E' in toString) { - val (beforeE, afterE) = toString.split('E') + if (toString.contains('E', ignoreCase = true)) { + val (beforeE, afterE) = toString.split('E', ignoreCase = true) val significand = beforeE.toDouble().toString().removeSuffix(".0") val exponent = afterE.toDouble().toString().removeSuffix(".0") @@ -108,9 +112,7 @@ public class PrettyPrintFloats(public val types: Set>) : Rend */ public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) - return null - + if (node !is MST.Numeric || node.value::class !in types) return null return printSignedNumberString(node.value.toString()) } @@ -282,15 +284,15 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { } } -public class Exponential(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax( +public class Exponent(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( operation = node.operation, - left = SymbolSyntax(string = "e"), - right = parent.render(node.value), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + useOperatorForm = true, ) public companion object { - public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION)) + public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..291399cee --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.ast.rendering + +internal expect fun Double.multiplatformToString(): String +internal expect fun Float.multiplatformToString(): String diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index 0ebb41b28..a08f089f1 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -16,69 +16,110 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit - is OperandSyntax -> perform(node.operand) + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform(node.operand) - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } - - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> perform(node.operand) - is RadicalSyntax -> perform(node.operand) - - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } - - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } - - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } - - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } - - is MultiplicationSyntax -> { - node.times = node.right.operand is NumberSyntax && !node.right.parentheses - || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax - || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax - || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax - - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) } + + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) + + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } + + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + node.times = node.right.operand is NumberSyntax && !node.right.parentheses + || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax + || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax + || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax + + perform(node.left) + perform(node.right) + } + } +} + + +/** + * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a + * superscript or a subscript to improve readability. + * + * @author Iaroslav Postovalov + */ +public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { + private fun perform0(node: MathSyntax): Boolean { + return when (node) { + is NumberSyntax -> false + is SymbolSyntax -> false + is OperatorNameSyntax -> false + is SpecialSymbolSyntax -> false + is OperandSyntax -> perform0(node.operand) + is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) + is UnaryPlusSyntax -> perform0(node.operand) + is UnaryMinusSyntax -> perform0(node.operand) + is RadicalSyntax -> perform0(node.operand) + + is ExponentSyntax -> { + val r = perform0(node.operand) + node.useOperatorForm = r + r + } + + is SuperscriptSyntax -> true + is SubscriptSyntax -> true + is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right) + is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) + is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) + is FractionSyntax -> true + is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) + is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) + } + } + + public override fun perform(node: MathSyntax) { + perform0(node) } } @@ -90,89 +131,89 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro */ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit - is OperandSyntax -> { - val isRightOfSuperscript = - (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node + is OperandSyntax -> { + val isRightOfSuperscript = + (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node - val precedence = precedenceFunction(node.operand) + val precedence = precedenceFunction(node.operand) - val needParenthesesByPrecedence = when (val parent = node.parent) { - null -> false + val needParenthesesByPrecedence = when (val parent = node.parent) { + null -> false - is BinarySyntax -> { - val parentPrecedence = precedenceFunction(parent) + is BinarySyntax -> { + val parentPrecedence = precedenceFunction(parent) - parentPrecedence < precedence || - parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right - } - - else -> precedence > precedenceFunction(parent) + parentPrecedence < precedence || + parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right } - node.parentheses = !isRightOfSuperscript - && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax) - - perform(node.operand) + else -> precedence > precedenceFunction(parent) } - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } + val isInsideExpOperator = + node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> { - perform(node.operand) - } - is RadicalSyntax -> perform(node.operand) + node.parentheses = !isRightOfSuperscript + && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } + perform(node.operand) + } - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) + } - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } - is MultiplicationSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt similarity index 97% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 14ceefc30..ca3a95bc8 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -package space.kscisnce.kmath.ast +package space.kscience.kmath.ast import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt similarity index 95% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index a0dcba9c0..185659a1f 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -3,9 +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. */ -package space.kscisnce.kmath.ast +package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 1584293ce..1ab20ed85 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -42,6 +42,22 @@ internal class TestFeatures { testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + testLatex(Numeric(0.001), "0.001") + testLatex(Numeric(0.0000001), "1\\times10^{-7}") + + testLatex(Numeric(Float.NaN), "NaN") + testLatex(Numeric(Float.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Float.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0f), "1") + testLatex(Numeric(-1.0f), "-1") + testLatex(Numeric(1.42f), "1.42") + testLatex(Numeric(-1.42f), "-1.42") + testLatex(Numeric(1e10f), "1\\times10^{10}") + testLatex(Numeric(1e-10f), "1\\times10^{-10}") + testLatex(Numeric(-1e-10f), "-1\\times10^{-10}") + testLatex(Numeric(-1e10f), "-1\\times10^{10}") + testLatex(Numeric(0.001f), "0.001") + testLatex(Numeric(0.0000001f), "1\\times10^{-7}") } @Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index a4017fdb4..599e43eb2 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -30,4 +30,11 @@ internal class TestStages { testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") testLatex("x^(x+x)", "x^{x+x}") } + + @Test + fun exponent() { + testLatex("exp(x)", "e^{x}") + testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)") + testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)") + } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..521907d2c --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.ast.rendering + +internal actual fun Double.multiplatformToString(): String { + val d = this + if (d >= 1e7 || d <= -1e7) return js("d.toExponential()") as String + return toString() +} + +internal actual fun Float.multiplatformToString(): String { + val d = this + if (d >= 1e7f || d <= -1e7f) return js("d.toExponential()") as String + return toString() +} diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..556adbe7d --- /dev/null +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.ast.rendering + +internal actual fun Double.multiplatformToString(): String = toString() +internal actual fun Float.multiplatformToString(): String = toString()