diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt new file mode 100644 index 000000000..1584293ce --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt @@ -0,0 +1,100 @@ +/* + * 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 + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST.Numeric +import kotlin.test.Test + +internal class TestFeatures { + @Test + fun printSymbolic() = testLatex("x", "x") + + @Test + fun printNumeric() { + val num = object : Number() { + override fun toByte(): Byte = throw UnsupportedOperationException() + override fun toChar(): Char = throw UnsupportedOperationException() + override fun toDouble(): Double = throw UnsupportedOperationException() + override fun toFloat(): Float = throw UnsupportedOperationException() + override fun toInt(): Int = throw UnsupportedOperationException() + override fun toLong(): Long = throw UnsupportedOperationException() + override fun toShort(): Short = throw UnsupportedOperationException() + override fun toString(): String = "foo" + } + + testLatex(Numeric(num), "foo") + } + + @Test + fun prettyPrintFloats() { + testLatex(Numeric(Double.NaN), "NaN") + testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0), "1") + testLatex(Numeric(-1.0), "-1") + testLatex(Numeric(1.42), "1.42") + testLatex(Numeric(-1.42), "-1.42") + testLatex(Numeric(1.1e10), "1.1\\times10^{10}") + 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}") + } + + @Test + fun prettyPrintIntegers() { + testLatex(Numeric(42), "42") + testLatex(Numeric(-42), "-42") + } + + @Test + fun prettyPrintPi() { + testLatex("pi", "\\pi") + } + + @Test + fun binaryPlus() = testLatex("2+2", "2+2") + + @Test + fun binaryMinus() = testLatex("2-2", "2-2") + + @Test + fun fraction() = testLatex("2/2", "\\frac{2}{2}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") + + @Test + fun power() = testLatex("x^y", "x^{y}") + + @Test + fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun exponential() = testLatex("exp(x)", "e^{x}") + + @Test + fun multiplication() = testLatex("x*1", "x\\times1") + + @Test + fun inverseTrigonometry() { + testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") + testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + } + +// @Test +// fun unaryPlus() { +// testLatex("+1", "+1") +// testLatex("+1", "++1") +// } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt new file mode 100644 index 000000000..6322df25d --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt @@ -0,0 +1,73 @@ +/* + * 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 + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestLatex { + @Test + fun number() = testLatex("42", "42") + + @Test + fun symbol() = testLatex("x", "x") + + @Test + fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun specialSymbol() { + testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex("pi", "\\pi") + } + + @Test + fun operand() { + testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + testLatex("1+1", "1+1") + } + + @Test + fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testLatex("-x", "-x") + + @Test + fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun superscript() = testLatex("x^y", "x^{y}") + + @Test + fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun binaryPlus() = testLatex("x+x", "x+x") + + @Test + fun binaryMinus() = testLatex("x-x", "x-x") + + @Test + fun fraction() = testLatex("x/x", "\\frac{x}{x}") + + @Test + fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") + + @Test + fun multiplication() { + testLatex("x*1", "x\\times1") + testLatex("1*x", "1\\,x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt new file mode 100644 index 000000000..2d7bfad19 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt @@ -0,0 +1,92 @@ +/* + * 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 + +import space.kscience.kmath.ast.rendering.TestUtils.testMathML +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestMathML { + @Test + fun number() = testMathML("42", "42") + + @Test + fun symbol() = testMathML("x", "x") + + @Test + fun operatorName() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun specialSymbol() { + testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + testMathML("pi", "π") + } + + @Test + fun operand() { + testMathML( + "sin(1)", + "sin1", + ) + + testMathML("1+1", "1+1") + } + + @Test + fun unaryOperator() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun unaryPlus() = + testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testMathML("-x", "-x") + + @Test + fun radical() = testMathML("sqrt(x)", "x") + + @Test + fun superscript() = testMathML("x^y", "xy") + + @Test + fun subscript() = testMathML( + SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), + "x123", + ) + + @Test + fun binaryOperator() = testMathML( + "f(x, y)", + "fx,y", + ) + + @Test + fun binaryPlus() = testMathML("x+x", "x+x") + + @Test + fun binaryMinus() = testMathML("x-x", "x-x") + + @Test + fun fraction() = testMathML("x/x", "xx") + + @Test + fun radicalWithIndex() = + testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), + "yx") + + @Test + fun multiplication() { + testMathML("x*1", "x×1") + testMathML("1*x", "1x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt new file mode 100644 index 000000000..a4017fdb4 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt @@ -0,0 +1,33 @@ +/* + * 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 + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import kotlin.test.Test + +internal class TestStages { + @Test + fun betterMultiplication() { + testLatex("a*1", "a\\times1") + testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") + testLatex("1*1", "1\\times1") + testLatex("2e10", "2\\times10^{10}") + testLatex("2*x", "2\\,x") + testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") + testLatex("x*y", "x\\,y") + } + + @Test + fun parentheses() { + testLatex("(x+1)", "x+1") + testLatex("x*x*x", "x\\,x\\,x") + testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") + testLatex("x+x*x", "x+x\\,x") + testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") + testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") + testLatex("x^(x+x)", "x^{x+x}") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt new file mode 100644 index 000000000..7c9400532 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt @@ -0,0 +1,46 @@ +/* + * 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 + +import space.kscience.kmath.ast.parseMath +import space.kscience.kmath.expressions.MST +import kotlin.test.assertEquals + +internal object TestUtils { + private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) + private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + + internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(mst), + ) + + internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(expression.parseMath()), + ) + + internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), + ) + + internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(mst), + ) + + internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(expression.parseMath()), + ) + + internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), + ) +}