diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..7273b6a50 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +@altavir + +/kmath-trajectory @ESchouten \ No newline at end of file diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml index 17e44e4d0..840e0c87c 100644 --- a/.idea/copyright/kmath.xml +++ b/.idea/copyright/kmath.xml @@ -1,6 +1,7 @@ - - - + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index b538bdf41..1c10bd6f5 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,5 +1,5 @@ - + diff --git a/.space.kts b/.space.kts index d70ad6d59..c9500e967 100644 --- a/.space.kts +++ b/.space.kts @@ -1,3 +1,3 @@ job("Build") { gradlew("openjdk:11", "build") -} +} \ No newline at end of file diff --git a/.space/CODEOWNERS b/.space/CODEOWNERS new file mode 100644 index 000000000..e69de29bb diff --git a/CHANGELOG.md b/CHANGELOG.md index 75833602c..feb925436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,16 @@ ## [Unreleased] ### Added +- 2D optimal trajectory computation in a separate module `kmath-trajectory` +- Autodiff for generic algebra elements in core! +- Algebra now has an obligatory `bufferFactory` (#477). ### Changed +- Major refactor of tensors (only minor API changes) +- Kotlin 1.7.20 +- `LazyStructure` `deffered` -> `async` to comply with coroutines code style +- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`. +- Multik went MPP ### Deprecated diff --git a/README.md b/README.md index aea94f529..03e803180 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) -![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) +![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) [![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) @@ -11,7 +11,7 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) +[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) ## Publications and talks @@ -44,7 +44,7 @@ module definitions below. The module stability could have the following levels: * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked - with `@UnstableKmathAPI` or other stability warning annotations. + with `@UnstableKMathAPI` or other stability warning annotations. * **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. @@ -86,8 +86,8 @@ module definitions below. The module stability could have the following levels: > **Maturity**: PROTOTYPE > > **Features:** -> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers -> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions +> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations +> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ### [kmath-core](kmath-core) @@ -214,6 +214,28 @@ One can still use generic algebras though. > > **Maturity**: EXPERIMENTAL +### [kmath-polynomial](kmath-polynomial) +> +> +> **Maturity**: PROTOTYPE +> +> **Features:** +> - [polynomial abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Abstraction for polynomial spaces. +> - [rational function abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt) : Abstraction for rational functions spaces. +> - ["list" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt) : List implementation of univariate polynomials. +> - ["list" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt) : List implementation of univariate rational functions. +> - ["list" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt) : Constructors for list polynomials and rational functions. +> - ["list" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt) : Utilities for list polynomials and rational functions. +> - ["numbered" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt) : Numbered implementation of multivariate polynomials. +> - ["numbered" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt) : Numbered implementation of multivariate rational functions. +> - ["numbered" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt) : Constructors for numbered polynomials and rational functions. +> - ["numbered" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt) : Utilities for numbered polynomials and rational functions. +> - ["labeled" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt) : Labeled implementation of multivariate polynomials. +> - ["labeled" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt) : Labeled implementation of multivariate rational functions. +> - ["labeled" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt) : Constructors for labeled polynomials and rational functions. +> - ["labeled" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt) : Utilities for labeled polynomials and rational functions. + + ### [kmath-stat](kmath-stat) > > @@ -240,11 +262,21 @@ One can still use generic algebras though. > - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +### [kmath-trajectory](kmath-trajectory) +> Path and trajectory optimization +> +> **Maturity**: PROTOTYPE + ### [kmath-viktor](kmath-viktor) > > > **Maturity**: DEVELOPMENT +### [test-utils](test-utils) +> +> +> **Maturity**: EXPERIMENTAL + ## Multi-platform support @@ -261,8 +293,7 @@ performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized -native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be -better than SciPy. +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. ## Requirements @@ -294,4 +325,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. +[waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 22712816d..9c8dc613a 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,5 +1,6 @@ @file:Suppress("UNUSED_VARIABLE") +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import space.kscience.kmath.benchmarks.addBenchmarkProperties plugins { @@ -15,6 +16,8 @@ repositories { mavenCentral() } +val multikVersion: String by rootProject.extra + kotlin { jvm() @@ -39,7 +42,9 @@ kotlin { implementation(project(":kmath-dimensions")) implementation(project(":kmath-for-real")) implementation(project(":kmath-tensors")) - implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2") + implementation(project(":kmath-multik")) + implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") + implementation(npmlibs.kotlinx.benchmark.runtime) } } @@ -51,7 +56,6 @@ kotlin { implementation(project(":kmath-kotlingrad")) implementation(project(":kmath-viktor")) implementation(project(":kmath-jafama")) - implementation(project(":kmath-multik")) implementation(projects.kmath.kmathTensorflow) implementation("org.tensorflow:tensorflow-core-platform:0.4.0") implementation("org.nd4j:nd4j-native:1.0.0-M1") @@ -155,7 +159,7 @@ kotlin.sourceSets.all { } } -tasks.withType { +tasks.withType { kotlinOptions { jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy" @@ -163,7 +167,7 @@ tasks.withType { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } addBenchmarkProperties() diff --git a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 126a2e648..fd1b4307a 100644 --- a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt index ff933997f..abfc8cbf2 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 188a48ca7..19795b9eb 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index 39819d407..41b9005e4 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 7d5ae310b..7cbe83113 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -13,10 +13,8 @@ import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.linearSpace -import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.tensorflow.produceWithTF import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra @@ -79,12 +77,12 @@ internal class DotBenchmark { } @Benchmark - fun multikDot(blackhole: Blackhole) = with(DoubleField.multikAlgebra) { + fun multikDot(blackhole: Blackhole) = with(multikAlgebra) { blackhole.consume(matrix1 dot matrix2) } @Benchmark - fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace(Buffer.Companion::auto)) { + fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace) { blackhole.consume(matrix1 dot matrix2) } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index db3524e67..4df5f372f 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt index 5d4eee7c0..041f7e92a 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index 4ff687aac..f7aac8199 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index e3b3dde05..141d0433b 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -13,14 +13,12 @@ import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ones import org.jetbrains.kotlinx.multik.ndarray.data.DN import org.jetbrains.kotlinx.multik.ndarray.data.DataType -import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.nd.BufferedFieldOpsND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.nd4j.nd4j import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.one import space.kscience.kmath.tensors.core.tensorAlgebra @@ -28,12 +26,6 @@ import space.kscience.kmath.viktor.viktorAlgebra @State(Scope.Benchmark) internal class NDFieldBenchmark { - @Benchmark - fun autoFieldAdd(blackhole: Blackhole) = with(autoField) { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - blackhole.consume(res) - } @Benchmark fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) { @@ -50,7 +42,7 @@ internal class NDFieldBenchmark { } @Benchmark - fun multikAdd(blackhole: Blackhole) = with(multikField) { + fun multikAdd(blackhole: Blackhole) = with(multikAlgebra) { var res: StructureND = one(shape) repeat(n) { res += 1.0 } blackhole.consume(res) @@ -78,7 +70,7 @@ internal class NDFieldBenchmark { } @Benchmark - fun multikInPlaceAdd(blackhole: Blackhole) = with(DoubleField.multikAlgebra) { + fun multikInPlaceAdd(blackhole: Blackhole) = with(multikAlgebra) { val res = Multik.ones(shape, DataType.DoubleDataType).wrap() repeat(n) { res += 1.0 } blackhole.consume(res) @@ -95,11 +87,9 @@ internal class NDFieldBenchmark { private const val dim = 1000 private const val n = 100 private val shape = intArrayOf(dim, dim) - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) private val specializedField = DoubleField.ndAlgebra - private val genericField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing) + private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j - private val multikField = DoubleField.multikAlgebra private val viktorField = DoubleField.viktorAlgebra } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt index 38e064e53..3ed7163b3 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index de301678c..25ce8410a 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,25 +10,19 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.ndAlgebra +import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) internal class ViktorBenchmark { - @Benchmark - fun automaticFieldAddition(blackhole: Blackhole) { - with(autoField) { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - blackhole.consume(res) - } - } @Benchmark - fun realFieldAddition(blackhole: Blackhole) { - with(realField) { + fun doubleFieldAddition(blackhole: Blackhole) { + with(doubleField) { var res: StructureND = one(shape) repeat(n) { res += 1.0 } blackhole.consume(res) @@ -58,8 +52,7 @@ internal class ViktorBenchmark { private val shape = Shape(dim, dim) // automatically build context most suited for given type. - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) - private val realField = DoubleField.ndAlgebra + private val doubleField = DoubleField.ndAlgebra private val viktorField = ViktorFieldND(dim, dim) } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index dfdd89d74..ea417e564 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,19 +10,17 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.BufferedFieldOpsND import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) internal class ViktorLogBenchmark { @Benchmark fun realFieldLog(blackhole: Blackhole) { - with(realField) { + with(doubleField) { val fortyTwo = structureND(shape) { 42.0 } var res = one(shape) repeat(n) { res = ln(fortyTwo) } @@ -54,8 +52,7 @@ internal class ViktorLogBenchmark { private val shape = Shape(dim, dim) // automatically build context most suited for given type. - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) - private val realField = DoubleField.ndAlgebra + private val doubleField = DoubleField.ndAlgebra private val viktorField = ViktorFieldND(dim, dim) } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt new file mode 100644 index 000000000..f6d278d83 --- /dev/null +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2018-2022 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.benchmarks + +import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.multik.MultikDoubleAlgebra + +val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 10f2385f5..120b0f35d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,10 @@ +import space.kscience.gradle.isInDevelopment +import space.kscience.gradle.useApache2Licence +import space.kscience.gradle.useSPCTeam + plugins { - id("ru.mipt.npm.gradle.project") - id("org.jetbrains.kotlinx.kover") version "0.5.0" + id("space.kscience.gradle.project") + id("org.jetbrains.kotlinx.kover") version "0.6.0" } allprojects { @@ -11,13 +15,13 @@ allprojects { } group = "space.kscience" - version = "0.3.0" + version = "0.3.1-dev-4" } subprojects { if (name.startsWith("kmath")) apply() - plugins.withId("org.jetbrains.dokka"){ + plugins.withId("org.jetbrains.dokka") { tasks.withType { dependsOn(tasks["assemble"]) @@ -31,7 +35,7 @@ subprojects { localDirectory.set(kotlinDir) remoteUrl.set( - java.net.URL("https://github.com/mipt-npm/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath") + java.net.URL("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath") ) } @@ -51,14 +55,38 @@ subprojects { } } } + + plugins.withId("org.jetbrains.kotlin.multiplatform") { + configure { + sourceSets { + val commonTest by getting { + dependencies { + implementation(projects.testUtils) + } + } + } + } + } } readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md") ksciencePublish { - github("kmath", addToRelease = false) - space() + pom("https://github.com/SciProgCentre/kmath") { + useApache2Licence() + useSPCTeam() + } + github("kmath", "SciProgCentre") + space( + if (isInDevelopment) { + "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/dev" + } else { + "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/release" + } + ) sonatype() } apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") + +val multikVersion by extra("0.2.0") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index fa5142538..0f95a7b3f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `kotlin-dsl` `version-catalog` - alias(miptNpmLibs.plugins.kotlin.plugin.serialization) + kotlin("plugin.serialization") version "1.6.21" } java.targetCompatibility = JavaVersion.VERSION_11 @@ -13,17 +13,18 @@ repositories { gradlePluginPortal() } -val toolsVersion: String by extra -val kotlinVersion = miptNpmLibs.versions.kotlin.asProvider().get() -val benchmarksVersion = miptNpmLibs.versions.kotlinx.benchmark.get() +val toolsVersion = npmlibs.versions.tools.get() +val kotlinVersion = npmlibs.versions.kotlin.asProvider().get() +val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get() dependencies { - api("ru.mipt.npm:gradle-tools:$toolsVersion") + api("space.kscience:gradle-tools:$toolsVersion") + api(npmlibs.atomicfu.gradle) //plugins form benchmarks api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion") api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //to be used inside build-script only - implementation(miptNpmLibs.kotlinx.serialization.json) + implementation(npmlibs.kotlinx.serialization.json) } kotlin.sourceSets.all { diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties deleted file mode 100644 index a0b05e812..000000000 --- a/buildSrc/gradle.properties +++ /dev/null @@ -1,7 +0,0 @@ -# -# 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. -# - -kotlin.code.style=official -toolsVersion=0.11.2-kotlin-1.6.10 diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 7c1df133d..403e0f52c 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -6,7 +6,17 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { - val toolsVersion: String by extra + val projectProperties = java.util.Properties() + file("../gradle.properties").inputStream().use { + projectProperties.load(it) + } + + projectProperties.forEach { key, value -> + extra.set(key.toString(), value) + } + + + val toolsVersion: String = projectProperties["toolsVersion"].toString() repositories { mavenLocal() @@ -16,8 +26,8 @@ dependencyResolutionManagement { } versionCatalogs { - create("miptNpmLibs") { - from("ru.mipt.npm:version-catalog:$toolsVersion") + create("npmlibs") { + from("space.kscience:version-catalog:$toolsVersion") } } } diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt index eaa0f59d8..62cf44915 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt index dc9327348..5c6a2ac83 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -9,7 +9,7 @@ import kotlinx.benchmark.gradle.BenchmarksExtension import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import org.gradle.api.Project -import ru.mipt.npm.gradle.KScienceReadmeExtension +import space.kscience.gradle.KScienceReadmeExtension import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt index 7f8cb35b3..183510232 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -319,7 +319,9 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, } else -> null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** diff --git a/docs/images/KM.svg b/docs/images/KM.svg index 6f80e4d08..55a4339b1 100644 --- a/docs/images/KM.svg +++ b/docs/images/KM.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KM_mono.svg b/docs/images/KM_mono.svg index 8f8e470b2..f1194f887 100644 --- a/docs/images/KM_mono.svg +++ b/docs/images/KM_mono.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KMath.svg b/docs/images/KMath.svg index f751d8eb9..509a184bc 100644 --- a/docs/images/KMath.svg +++ b/docs/images/KMath.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KMath_mono.svg b/docs/images/KMath_mono.svg index 8ca6c5e84..e781979e2 100644 --- a/docs/images/KMath_mono.svg +++ b/docs/images/KMath_mono.svg @@ -1,6 +1,6 @@ diff --git a/docs/polynomials.md b/docs/polynomials.md new file mode 100644 index 000000000..b255acda1 --- /dev/null +++ b/docs/polynomials.md @@ -0,0 +1,172 @@ +# Polynomials and Rational Functions + +KMath provides a way to work with uni- and multivariate polynomials and rational functions. It includes full support of arithmetic operations of integers, **constants** (elements of ring polynomials are build over), variables (for certain multivariate implementations), polynomials and rational functions encapsulated in so-called **polynomial space** and **rational function space** and some other utilities such as algebraic differentiation and substitution. + +## Concrete realizations + +There are 3 approaches to represent polynomials: +1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (Compare to sequential definition of polynomials.) +2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map" or "dictionary", in math it is called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding coefficient of the term. But there are 2 possible approaches of term signature representation: + 1. One can number all the variables, so term signature can be represented as a sequence describing powers of the variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be represented as a finite sequence $(d_0; \dots; d_n)$. + 2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of each appeared variable with its power in the term. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural non-zero $d_i $) can be represented as a finite matching $(x_0 \to d_1; \dots; x_n \to d_n)$. + +All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or more precisely, as any field of fractions over integral domain) should be implemented. + +So here are a bit of details. Let `C` by type of constants. Then: +1. `ListPolynomial`, `ListPolynomialSpace`, `ListRationalFunction` and `ListRationalFunctionSpace` implement the first scenario. `ListPolynomial` stores polynomial $a_0 + \dots + a_n x^n $ as a coefficients list `listOf(a_0, ..., a_n)` (of type `List`). + + They also have variation `ScalableListPolynomialSpace` that replaces former polynomials and implements `ScaleOperations`. +2. `NumberedPolynomial`, `NumberedPolynomialSpace`, `NumberedRationalFunction` and `NumberedRationalFunctionSpace` implement second scenario. `NumberedPolynomial` stores polynomials as structures of type `Map, C>`. Signatures are stored as `List`. To prevent ambiguity signatures should not end with zeros. +3. `LabeledPolynomial`, `LabeledPolynomialSpace`, `LabeledRationalFunction` and `LabeledRationalFunctionSpace` implement third scenario using common `Symbol` as variable type. `LabeledPolynomial` stores polynomials as structures of type `Map, C>`. Signatures are stored as `Map`. To prevent ambiguity each signature should not map any variable to zero. + +### Example: `ListPolynomial` + +For example, polynomial $2 - 3x + x^2 $ (with `Int` coefficients) is represented +```kotlin +val polynomial: ListPolynomial = ListPolynomial(listOf(2, -3, 1)) +// or +val polynomial: ListPolynomial = ListPolynomial(2, -3, 1) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.listPolynomialSpace { + ListPolynomial(2, -3, 1) + ListPolynomial(0, 6) == ListPolynomial(2, 3, 1) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +### Example: `NumberedPolynomial` + +For example, polynomial $3 + 5 x_1 - 7 x_0^2 x_2 $ (with `Int` coefficients) is represented +```kotlin +val polynomial: NumberedPolynomial = NumberedPolynomial( + mapOf( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) +) +// or +val polynomial: NumberedPolynomial = NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, +) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.numberedPolynomialSpace { + NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + NumberedPolynomial( + listOf(0u, 1u) to -5, + listOf(0u, 0u, 0u, 4u) to 4, + ) == NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 0, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to 4, + ) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +### Example: `LabeledPolynomial` + +For example, polynomial $3 + 5 y - 7 x^2 z $ (with `Int` coefficients) is represented +```kotlin +val polynomial: LabeledPolynomial = LabeledPolynomial( + mapOf( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, + ) +) +// or +val polynomial: LabeledPolynomial = LabeledPolynomial( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, +) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.labeledPolynomialSpace { + LabeledPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + LabeledPolynomial( + listOf(0u, 1u) to -5, + listOf(0u, 0u, 0u, 4u) to 4, + ) == LabeledPolynomial( + listOf() to 3, + listOf(0u, 1u) to 0, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to 4, + ) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +## Abstract entities (interfaces and abstract classes) + +```mermaid +classDiagram + Polynomial <|-- ListPolynomial + Polynomial <|-- NumberedPolynomial + Polynomial <|-- LabeledPolynomial + + RationalFunction <|-- ListRationalFunction + RationalFunction <|-- NumberedRationalFunction + RationalFunction <|-- LabeledRationalFunction + + Ring <|-- PolynomialSpace + PolynomialSpace <|-- MultivariatePolynomialSpace + PolynomialSpace <|-- PolynomialSpaceOverRing + + Ring <|-- RationalFunctionSpace + RationalFunctionSpace <|-- MultivariateRationalFunctionSpace + RationalFunctionSpace <|-- RationalFunctionSpaceOverRing + RationalFunctionSpace <|-- RationalFunctionSpaceOverPolynomialSpace + RationalFunctionSpace <|-- PolynomialSpaceOfFractions + RationalFunctionSpaceOverPolynomialSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace + MultivariateRationalFunctionSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace + MultivariateRationalFunctionSpace <|-- MultivariatePolynomialSpaceOfFractions + PolynomialSpaceOfFractions <|-- MultivariatePolynomialSpaceOfFractions +``` + +There are implemented `Polynomial` and `RationalFunction` interfaces as abstractions of polynomials and rational functions respectively (although, there is not a lot of logic in them) and `PolynomialSpace` and `RationalFunctionSpace` (that implement `Ring` interface) as abstractions of polynomials' and rational functions' spaces respectively. More precisely, that means they allow to declare common logic of interaction with such objects and spaces: +- `Polynomial` does not provide any logic. It is marker interface. +- `RationalFunction` provides numerator and denominator of rational function and destructuring declaration for them. +- `PolynomialSpace` provides all possible arithmetic interactions of integers, constants (of type `C`), and polynomials (of type `P`) like addition, subtraction, multiplication, and some others and common properties like degree of polynomial. +- `RationalFunctionSpace` provides the same as `PolynomialSpace` but also for rational functions: all possible arithmetic interactions of integers, constants (of type `C`), polynomials (of type `P`), and rational functions (of type `R`) like addition, subtraction, multiplication, division (in some cases), and some others and common properties like degree of polynomial. + +Then to add abstraction of similar behaviour with variables (in multivariate case) there are implemented `MultivariatePolynomialSpace` and `MultivariateRationalFunctionSpace`. They just include variables (of type `V`) in the interactions of the entities. + +Also, to remove boilerplates there were provided helping subinterfaces and abstract subclasses: +- `PolynomialSpaceOverRing` allows to replace implementation of interactions of integers and constants with implementations from provided ring over constants (of type `A: Ring`). +- `RationalFunctionSpaceOverRing` — the same but for `RationalFunctionSpace`. +- `RationalFunctionSpaceOverPolynomialSpace` — the same but "the inheritance" includes interactions with polynomials from provided `PolynomialSpace`. +- `PolynomialSpaceOfFractions` is actually abstract subclass of `RationalFunctionSpace` that implements all fractions boilerplates with provided (`protected`) constructor of rational functions by polynomial numerator and denominator. +- `MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace` and `MultivariatePolynomialSpaceOfFractions` — the same stories of operators inheritance and fractions boilerplates respectively but in multivariate case. + +## Utilities + +For all kinds of polynomials there are provided (implementation details depend on kind of polynomials) such common utilities as: +1. differentiation and anti-differentiation, +2. substitution, invocation and functional representation. \ No newline at end of file diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 4ffa9e75f..d7d5a806d 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -1,6 +1,6 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) -![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) +![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) [![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) @@ -11,7 +11,7 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) +[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) ## Publications and talks @@ -44,7 +44,7 @@ module definitions below. The module stability could have the following levels: * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked - with `@UnstableKmathAPI` or other stability warning annotations. + with `@UnstableKMathAPI` or other stability warning annotations. * **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. @@ -69,8 +69,7 @@ performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized -native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be -better than SciPy. +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. ## Requirements @@ -102,4 +101,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 60f8f5aed..1d224bace 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -8,6 +8,8 @@ repositories { maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") } +val multikVersion: String by rootProject.extra + dependencies { implementation(project(":kmath-ast")) implementation(project(":kmath-kotlingrad")) @@ -15,6 +17,8 @@ dependencies { implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) implementation(project(":kmath-complex")) + implementation(project(":kmath-functions")) + implementation(project(":kmath-polynomial")) implementation(project(":kmath-optimization")) implementation(project(":kmath-stat")) implementation(project(":kmath-viktor")) @@ -28,6 +32,7 @@ dependencies { implementation(project(":kmath-jafama")) //multik implementation(project(":kmath-multik")) + implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") implementation("org.nd4j:nd4j-native:1.0.0-beta7") @@ -66,5 +71,5 @@ tasks.withType { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt index c4f263f97..e85bab8d8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 907f1bbe4..cacb6683e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index dec3bfb81..b443e639d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt index 7e09faeff..92ee1781b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt index 63e57bd8c..e32b97136 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt index d52976671..73fca8a38 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 59eaba5bd..28169f15a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt index 8dbc7b7a4..b4ce6ad2d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt index a50df0931..7bcd96990 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 4f99aeb47..1b578626d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt new file mode 100644 index 000000000..8228983e2 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt @@ -0,0 +1,399 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.invoke + + +/** + * Shows [ListPolynomial]s' and [ListRationalFunction]s' capabilities. + */ +fun listPolynomialsExample() { + // [ListPolynomial] is a representation of a univariate polynomial as a list of coefficients from the least term to + // the greatest term. For example, + val polynomial1: ListPolynomial = ListPolynomial(listOf(2, -3, 1)) + // represents polynomial 2 + (-3) x + x^2 + + // There are also shortcut fabrics: + val polynomial2: ListPolynomial = ListPolynomial(2, -3, 1) + println(polynomial1 == polynomial2) // true + // and even + val polynomial3: ListPolynomial = 57.asListPolynomial() + val polynomial4: ListPolynomial = ListPolynomial(listOf(57)) + println(polynomial3 == polynomial4) // true + + val polynomial5: ListPolynomial = ListPolynomial(3, -1) + // For every ring there can be provided a polynomial ring: + Int.algebra.listPolynomialSpace { + println(-polynomial5 == ListPolynomial(-3, 1)) // true + println(polynomial1 + polynomial5 == ListPolynomial(5, -4, 1)) // true + println(polynomial1 - polynomial5 == ListPolynomial(-1, -2, 1)) // true + println(polynomial1 * polynomial5 == ListPolynomial(6, -11, 6, -1)) // true + } + // You can even write + val x: ListPolynomial = ListPolynomial(0.0, 1.0) + val polynomial6: ListPolynomial = ListPolynomial(2.0, -3.0, 1.0) + Double.algebra.listPolynomialSpace { + println(2 - 3 * x + x * x == polynomial6) + println(2.0 - 3.0 * x + x * x == polynomial6) + } + + // Also there are some utilities for polynomials: + println(polynomial1.substitute(Int.algebra, 1) == 0) // true, because 2 + (-3) * 1 + 1^2 = 0 + println(polynomial1.substitute(Int.algebra, polynomial5) == polynomial1) // true, because 2 + (-3) * (3-x) + (3-x)^2 = 2 - 3x + x^2 + println(polynomial1.derivative(Int.algebra) == ListPolynomial(-3, 2)) // true, (2 - 3x + x^2)' = -3 + 2x + println(polynomial1.nthDerivative(Int.algebra, 2) == 2.asListPolynomial()) // true, (2 - 3x + x^2)'' = 2 + + // Lastly, there are rational functions and some other utilities: + Double.algebra.listRationalFunctionSpace { + val rationalFunction1: ListRationalFunction = ListRationalFunction(listOf(2.0, -3.0, 1.0), listOf(3.0, -1.0)) + // It's just (2 - 3x + x^2)/(3 - x) + + val rationalFunction2 : ListRationalFunction = ListRationalFunction(listOf(5.0, -4.0, 1.0), listOf(3.0, -1.0)) + // It's just (5 - 4x + x^2)/(3 - x) + + println(rationalFunction1 + 1 == rationalFunction2) + } +} + +/** + * Shows [NumberedPolynomial]s' and [NumberedRationalFunction]s' capabilities. + */ +fun numberedPolynomialsExample() { + // Consider polynomial + // 3 + 5 x_2 - 7 x_1^2 x_3 + // Consider, for example, its term -7 x_1^2 x_3. -7 is a coefficient of the term, whereas (2, 0, 1, 0, 0, ...) is + // description of degrees of variables x_1, x_2, ... in the term. Such description with removed leading zeros + // [2, 0, 1] is called "signature" of the term -7 x_1^2 x_3. + + val polynomial1: NumberedPolynomial + with(Int.algebra) { + // [NumberedPolynomial] is a representation of a multivariate polynomial, that stores terms in a map with terms' + // signatures as the map's keys and terms' coefficients as corresponding values. For example, + polynomial1 = NumberedPolynomial( + mapOf( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + ) + // represents polynomial 3 + 5 x_2 - 7 x_1^2 x_3 + + // This `NumberedPolynomial` function needs context of either ring of constant (as `Int.algebra` in this example) + // or space of NumberedPolynomials over it. To understand why it is like this see documentations of functions + // NumberedPolynomial and NumberedPolynomialWithoutCheck + + // There are also shortcut fabrics: + val polynomial2: NumberedPolynomial = NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + println(polynomial1 == polynomial2) // true + // and even + val polynomial3: NumberedPolynomial = 57.asNumberedPolynomial() // This one actually does not algebraic context! + val polynomial4: NumberedPolynomial = NumberedPolynomial(listOf() to 57) + println(polynomial3 == polynomial4) // true + + numberedPolynomialSpace { + // Also there is DSL for constructing NumberedPolynomials: + val polynomial5: NumberedPolynomial = NumberedPolynomialDSL1 { + 3 {} + 5 { 1 inPowerOf 1u } + -7 with { 0 pow 2u; 2 pow 1u } + // `pow` and `inPowerOf` are the same + // `with` is omittable + } + println(polynomial1 == polynomial5) // true + + // Unfortunately the DSL does not work good in bare context of constants' ring, so for now it's disabled and + // works only in NumberedPolynomialSpace and NumberedRationalFunctionSpace + } + } + + val polynomial6: NumberedPolynomial = Int.algebra { + NumberedPolynomial( + listOf() to 7, + listOf(0u, 1u) to -5, + listOf(2u, 0u, 1u) to 0, + listOf(0u, 0u, 0u, 4u) to 4, + ) + } + // For every ring there can be provided a polynomial ring: + Int.algebra.numberedPolynomialSpace { + println( + -polynomial6 == NumberedPolynomial( + listOf() to -7, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to 0, + listOf(0u, 0u, 0u, 4u) to (-4), + ) + ) // true + println( + polynomial1 + polynomial6 == NumberedPolynomial( + listOf() to 10, + listOf(0u, 1u) to 0, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to 4, + ) + ) // true + println( + polynomial1 - polynomial6 == NumberedPolynomial( + listOf() to -4, + listOf(0u, 1u) to 10, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to -4, + ) + ) // true + + polynomial1 * polynomial6 // Multiplication works too + } + + Double.algebra.numberedPolynomialSpace { + // You can even write + val x_1: NumberedPolynomial = NumberedPolynomial(listOf(1u) to 1.0) + val x_2: NumberedPolynomial = NumberedPolynomial(listOf(0u, 1u) to 1.0) + val x_3: NumberedPolynomial = NumberedPolynomial(listOf(0u, 0u, 1u) to 1.0) + val polynomial7: NumberedPolynomial = NumberedPolynomial( + listOf() to 3.0, + listOf(0u, 1u) to 5.0, + listOf(2u, 0u, 1u) to -7.0, + ) + Double.algebra.listPolynomialSpace { + println(3 + 5 * x_2 - 7 * x_1 * x_1 * x_3 == polynomial7) + println(3.0 + 5.0 * x_2 - 7.0 * x_1 * x_1 * x_3 == polynomial7) + } + } + + Int.algebra.numberedPolynomialSpace { + val x_4: NumberedPolynomial = NumberedPolynomial(listOf(0u, 0u, 0u, 4u) to 1) + // Also there are some utilities for polynomials: + println(polynomial1.substitute(mapOf(0 to 1, 1 to -2, 2 to -1)) == 0.asNumberedPolynomial()) // true, + // because it's substitution x_1 -> 1, x_2 -> -2, x_3 -> -1, + // so 3 + 5 x_2 - 7 x_1^2 x_3 = 3 + 5 * (-2) - 7 * 1^2 * (-1) = 3 - 10 + 7 = 0 + println( + polynomial1.substitute(mapOf(1 to x_4)) == NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + ) // true, because it's substitution x_2 -> x_4, so result is 3 + 5 x_4 - 7 x_1^2 x_3 + println( + polynomial1.derivativeWithRespectTo(Int.algebra, 1) == + NumberedPolynomial(listOf() to 5) + ) // true, d/dx_2 (3 + 5 x_2 - 7 x_1^2 x_3) = 5 + } + + // Lastly, there are rational functions and some other utilities: + Double.algebra.numberedRationalFunctionSpace { + val rationalFunction1: NumberedRationalFunction = NumberedRationalFunction( + NumberedPolynomial( + listOf() to 2.0, + listOf(1u) to -3.0, + listOf(2u) to 1.0, + ), + NumberedPolynomial( + listOf() to 3.0, + listOf(1u) to -1.0, + ) + ) + // It's just (2 - 3x + x^2)/(3 - x) where x = x_1 + + val rationalFunction2: NumberedRationalFunction = NumberedRationalFunction( + NumberedPolynomial( + listOf() to 5.0, + listOf(1u) to -4.0, + listOf(2u) to 1.0, + ), + NumberedPolynomial( + listOf() to 3.0, + listOf(1u) to -1.0, + ) + ) + // It's just (5 - 4x + x^2)/(3 - x) where x = x_1 + + println(rationalFunction1 + 1 == rationalFunction2) + } +} + +/** + * Shows [LabeledPolynomial]s' and [LabeledRationalFunction]s' capabilities. + */ +fun labeledPolynomialsExample() { + val x by symbol + val y by symbol + val z by symbol + val t by symbol + + // Consider polynomial + // 3 + 5 y - 7 x^2 z + // Consider, for example, its term -7 x^2 z. -7 is a coefficient of the term, whereas matching (x -> 2, z -> 3) is + // description of degrees of variables x_1, x_2, ... in the term. Such description is called "signature" of the + // term -7 x_1^2 x_3. + + val polynomial1: LabeledPolynomial + with(Int.algebra) { + // [LabeledPolynomial] is a representation of a multivariate polynomial, that stores terms in a map with terms' + // signatures as the map's keys and terms' coefficients as corresponding values. For example, + polynomial1 = LabeledPolynomial( + mapOf( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, + ) + ) + // represents polynomial 3 + 5 y - 7 x^2 z + + // This `LabeledPolynomial` function needs context of either ring of constant (as `Int.algebra` in this example) + // or space of LabeledPolynomials over it. To understand why it is like this see documentations of functions + // LabeledPolynomial and LabeledPolynomialWithoutCheck + + // There are also shortcut fabrics: + val polynomial2: LabeledPolynomial = LabeledPolynomial( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, + ) + println(polynomial1 == polynomial2) // true + // and even + val polynomial3: LabeledPolynomial = 57.asLabeledPolynomial() // This one actually does not algebraic context! + val polynomial4: LabeledPolynomial = LabeledPolynomial(mapOf() to 57) + println(polynomial3 == polynomial4) // true + + labeledPolynomialSpace { + // Also there is DSL for constructing NumberedPolynomials: + val polynomial5: LabeledPolynomial = LabeledPolynomialDSL1 { + 3 {} + 5 { y inPowerOf 1u } + -7 with { x pow 2u; z pow 1u } + // `pow` and `inPowerOf` are the same + // `with` is omittable + } + println(polynomial1 == polynomial5) // true + + // Unfortunately the DSL does not work good in bare context of constants' ring, so for now it's disabled and + // works only in NumberedPolynomialSpace and NumberedRationalFunctionSpace + } + } + + val polynomial6: LabeledPolynomial = Int.algebra { + LabeledPolynomial( + mapOf() to 7, + mapOf(y to 1u) to -5, + mapOf(x to 2u, z to 1u) to 0, + mapOf(t to 4u) to 4, + ) + } + // For every ring there can be provided a polynomial ring: + Int.algebra.labeledPolynomialSpace { + println( + -polynomial6 == LabeledPolynomial( + mapOf() to -7, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to 0, + mapOf(t to 4u) to -4, + ) + ) // true + println( + polynomial1 + polynomial6 == LabeledPolynomial( + mapOf() to 10, + mapOf(y to 1u) to 0, + mapOf(x to 2u, z to 1u) to -7, + mapOf(t to 4u) to 4, + ) + ) // true + println( + polynomial1 - polynomial6 == LabeledPolynomial( + mapOf() to -4, + mapOf(y to 1u) to 10, + mapOf(x to 2u, z to 1u) to -7, + mapOf(t to 4u) to -4, + ) + ) // true + + polynomial1 * polynomial6 // Multiplication works too + } + + Double.algebra.labeledPolynomialSpace { + // You can even write + val polynomial7: LabeledPolynomial = LabeledPolynomial( + mapOf() to 3.0, + mapOf(y to 1u) to 5.0, + mapOf(x to 2u, z to 1u) to -7.0, + ) + Double.algebra.listPolynomialSpace { + println(3 + 5 * y - 7 * x * x * z == polynomial7) + println(3.0 + 5.0 * y - 7.0 * x * x * z == polynomial7) + } + } + + Int.algebra.labeledPolynomialSpace { + // Also there are some utilities for polynomials: + println(polynomial1.substitute(mapOf(x to 1, y to -2, z to -1)) == 0.asLabeledPolynomial()) // true, + // because it's substitution x -> 1, y -> -2, z -> -1, + // so 3 + 5 y - 7 x^2 z = 3 + 5 * (-2) - 7 * 1^2 * (-1) = 3 - 10 + 7 = 0 + println( + polynomial1.substitute(mapOf(y to t.asPolynomial())) == LabeledPolynomial( + mapOf() to 3, + mapOf(t to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, + ) + ) // true, because it's substitution y -> t, so result is 3 + 5 t - 7 x^2 z + println( + polynomial1.derivativeWithRespectTo(Int.algebra, y) == LabeledPolynomial(mapOf() to 5) + ) // true, d/dy (3 + 5 y - 7 x^2 z) = 5 + } + + // Lastly, there are rational functions and some other utilities: + Double.algebra.labeledRationalFunctionSpace { + val rationalFunction1: LabeledRationalFunction = LabeledRationalFunction( + LabeledPolynomial( + mapOf() to 2.0, + mapOf(x to 1u) to -3.0, + mapOf(x to 2u) to 1.0, + ), + LabeledPolynomial( + mapOf() to 3.0, + mapOf(x to 1u) to -1.0, + ) + ) + // It's just (2 - 3x + x^2)/(3 - x) + + val rationalFunction2: LabeledRationalFunction = LabeledRationalFunction( + LabeledPolynomial( + mapOf() to 5.0, + mapOf(x to 1u) to -4.0, + mapOf(x to 2u) to 1.0, + ), + LabeledPolynomial( + mapOf() to 3.0, + mapOf(x to 1u) to -1.0, + ) + ) + // It's just (5 - 4x + x^2)/(3 - x) + + println(rationalFunction1 + 1 == rationalFunction2) + } +} + +fun main() { + println("ListPolynomials:") + listPolynomialsExample() + println() + + println("NumberedPolynomials:") + numberedPolynomialsExample() + println() + + println("ListPolynomials:") + labeledPolynomialsExample() + println() +} diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt index 9c3d0fdbe..52451e9f3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt index a2d7d7c27..d9c3281f2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index a01ea7fe2..52ed8f05f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt index 51f439612..2447d06ed 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt index 2e1801cc2..77cfca4ae 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -7,7 +7,6 @@ package space.kscience.kmath.operations import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.algebra -import space.kscience.kmath.complex.bufferAlgebra import space.kscience.kmath.complex.ndAlgebra import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.StructureND @@ -18,7 +17,7 @@ fun main() = Complex.algebra { println(complex * 8 - 5 * i) //flat buffer - val buffer = with(bufferAlgebra){ + val buffer = with(bufferAlgebra) { buffer(8) { Complex(it, -it) }.map { Complex(it.im, it.re) } } println(buffer) @@ -30,7 +29,7 @@ fun main() = Complex.algebra { println(element) // 1d element operation - val result: StructureND = ndAlgebra{ + val result: StructureND = ndAlgebra { val a = structureND(8) { (it) -> i * it - it.toDouble() } val b = 3 val c = Complex(1.0, 1.0) diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt index 62c9c8076..8fc6e1b06 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index 8e3cdf86f..bdbf42797 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt index 15654971f..3de9b6f34 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt index d55f3df09..86d7c0d89 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index b680e267d..48d14cb4c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -32,12 +32,10 @@ fun main() { val shape = Shape(dim, dim) - // automatically build context most suited for given type. - val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) // specialized nd-field for Double. It works as generic Double field as well. - val realField = DoubleField.ndAlgebra - //A generic boxing field. It should be used for objects, not primitives. - val boxingField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing) + val doubleField = DoubleField.ndAlgebra + //A generic field. It should be used for objects, not primitives. + val genericField = BufferedFieldOpsND(DoubleField) // Nd4j specialized field. val nd4jField = DoubleField.nd4j //viktor field @@ -46,14 +44,14 @@ fun main() { val parallelField = DoubleField.ndStreaming(dim, dim) measureAndPrint("Boxing addition") { - boxingField { + genericField { var res: StructureND = one(shape) repeat(n) { res += 1.0 } } } measureAndPrint("Specialized addition") { - realField { + doubleField { var res: StructureND = one(shape) repeat(n) { res += 1.0 } } @@ -80,15 +78,8 @@ fun main() { } } - measureAndPrint("Automatic field addition") { - autoField { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - } - } - measureAndPrint("Lazy addition") { - val res = realField.one(shape).mapAsync(GlobalScope) { + val res = doubleField.one(shape).mapAsync(GlobalScope) { var c = 0.0 repeat(n) { c += 1.0 diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index 548fb16c1..4aa420305 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -1,10 +1,11 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.structures +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField @@ -49,6 +50,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND.map( transform: DoubleField.(Double) -> Double, ): BufferND { @@ -56,6 +58,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): BufferND { @@ -69,6 +72,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND, right: StructureND, diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index de36c664d..a64ac7280 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index dea7095a8..ce5301a7b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt index 889ea99bd..2ac0dc6a4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt index c28b566b9..1ba0e3503 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index b42602988..d0b24de70 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -1,10 +1,11 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra @@ -13,6 +14,7 @@ import kotlin.math.abs // OLS estimator using SVD +@OptIn(PerformancePitfall::class) fun main() { //seed for random val randSeed = 100500L @@ -50,7 +52,7 @@ fun main() { // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it }) - val alphaOLS = v dot sigma dot u.transpose() dot y + val alphaOLS = v dot sigma dot u.transposed() dot y println("Estimated alpha:\n" + "$alphaOLS") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index aced0cf7d..1768be283 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -27,7 +27,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with println("y:\n$y") // stack them into single dataset - val dataset = stack(listOf(x, y)).transpose() + val dataset = stack(listOf(x, y)).transposed() // normalize both x and y val xMean = x.mean() @@ -58,7 +58,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // and find out eigenvector of it val (_, evecs) = covMatrix.symEig() - val v = evecs[0] + val v = evecs.getTensor(0) println("Eigenvector:\n$v") // reduce dimension of dataset @@ -68,7 +68,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // we can restore original data from reduced data; // for example, find 7th element of dataset. val n = 7 - val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean - println("Original value:\n${dataset[n]}") + val restored = (datasetReduced.getTensor(n) dot v.view(intArrayOf(1, 2))) * std + mean + println("Original value:\n${dataset.getTensor(n)}") println("Restored value:\n$restored") } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt index a436ae1c3..6d72fd623 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt index f465fc424..64cc138d7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -66,7 +66,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n) { - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)] } return x } @@ -75,7 +75,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat // create it by placing ones on side diagonal - val revMat = u.zeroesLike() + val revMat = zeroesLike(u) val n = revMat.shape[0] for (i in 0 until n) { revMat[intArrayOf(i, n - 1 - i)] = 1.0 diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt index f2d1f0b41..67e0631e7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -7,11 +7,14 @@ package space.kscience.kmath.tensors import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarray -import space.kscience.kmath.multik.multikAlgebra +import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.multik.MultikDoubleAlgebra import space.kscience.kmath.nd.one -import space.kscience.kmath.operations.DoubleField -fun main(): Unit = with(DoubleField.multikAlgebra) { + +val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) + +fun main(): Unit = with(multikAlgebra) { val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType().wrap() val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap() one(a.shape) - a + b * 3.0 diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt index 5c41ab0f1..84d6dcd22 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -1,15 +1,16 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors +import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra -import space.kscience.kmath.tensors.core.copyArray +import space.kscience.kmath.tensors.core.toDoubleTensor import kotlin.math.sqrt const val seed = 100500L @@ -79,9 +80,9 @@ class Dense( } override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { - val gradInput = outputError dot weights.transpose() + val gradInput = outputError dot weights.transposed() - val gradW = input.transpose() dot outputError + val gradW = input.transposed() dot outputError val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() weights -= learningRate * gradW @@ -106,12 +107,11 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { } // neural network class -@OptIn(ExperimentalStdlibApi::class) class NeuralNetwork(private val layers: List) { private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { - val onesForAnswers = yPred.zeroesLike() - yTrue.copyArray().forEachIndexed { index, labelDouble -> + val onesForAnswers = zeroesLike(yPred) + yTrue.source.asIterable().forEachIndexed { index, labelDouble -> val label = labelDouble.toInt() onesForAnswers[intArrayOf(index, label)] = 1.0 } @@ -163,7 +163,7 @@ class NeuralNetwork(private val layers: List) { for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) { train(xBatch, yBatch) } - println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true).asDouble())}") + println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true).toDoubleTensor())}") } } @@ -194,7 +194,7 @@ fun main() = BroadcastDoubleTensorAlgebra { val y = fromArray( intArrayOf(sampleSize, 1), DoubleArray(sampleSize) { i -> - if (x[i].sum() > 0.0) { + if (x.getTensor(i).sum() > 0.0) { 1.0 } else { 0.0 @@ -230,7 +230,7 @@ fun main() = BroadcastDoubleTensorAlgebra { val prediction = model.predict(xTest) // process raw prediction via argMax - val predictionLabels = prediction.argMax(1, true).asDouble() + val predictionLabels = prediction.argMax(1, true).toDoubleTensor() // find out accuracy val acc = accuracy(yTest, predictionLabels) diff --git a/gradle.properties b/gradle.properties index 80108737e..0d1506980 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,8 +6,10 @@ kotlin.code.style=official kotlin.jupyter.add.scanner=false kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -#kotlin.incremental.js.ir=true +kotlin.incremental.js.ir=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.parallel=true +org.gradle.jvmargs=-Xmx4096m + +toolsVersion=0.13.0-kotlin-1.7.20-Beta diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fcea..8049c684f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 5d5630f46..c6da64982 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0' + implementation 'space.kscience:kmath-ast:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0") + implementation("space.kscience:kmath-ast:0.3.1-dev-1") } ``` @@ -199,10 +199,7 @@ public fun main() { Result LaTeX: -
- -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -
+$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 15b1d0900..7fd0f43f7 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,6 +1,9 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.js { @@ -24,7 +27,7 @@ kotlin.sourceSets { commonMain { dependencies { - api("com.github.h0tk3y.betterParse:better-parse:0.4.2") + api("com.github.h0tk3y.betterParse:better-parse:0.4.4") api(project(":kmath-core")) } } @@ -57,11 +60,11 @@ tasks.dokkaHtml { if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1") tasks.jvmTest { - jvmArgs = (jvmArgs ?: emptyList()) + listOf("-Dspace.kscience.kmath.ast.dump.generated.classes=1") + jvmArgs("-Dspace.kscience.kmath.ast.dump.generated.classes=1") } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index e9e22f4d4..96bbfbf5a 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -170,10 +170,7 @@ public fun main() { Result LaTeX: -
- -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -
+$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt index 8a8b8797d..6458dc123 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt index 71fb154c9..e411cd251 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index 012a6e65f..2c9a2a9ad 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 2df3d3cc7..13806703c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 8b5819b84..bd941745b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 fdef35ebd..dd8ed3457 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 ee23ab408..14df5ad8d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 362c07d72..e19a9722e 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 90f78a152..c1a895015 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 index 291399cee..dce99cc5a 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt index c0271fbb5..f42237ba6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index 1edb5923e..3400db0f8 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt index be8a92f3e..bf56b80a6 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index 93ef97b0f..f23d36240 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt index 954a0f330..95b804455 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt index d0c3a789e..d3c203903 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt index 42cf5ce58..4b3631663 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index a40c785b9..7b5ec5765 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt index 43f31baba..66c0ae1ae 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt index 145055494..8bc014c54 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index 09ec127c7..306538d5d 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index bf87b6fd0..79f178eef 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt index ec7436188..fe035c69f 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 index 521907d2c..f6411334c 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index a8b1aa2e1..853f5f983 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -36,7 +36,7 @@ public fun MST.compileToExpression(algebra: Algebra): Expression ) } - return ESTreeBuilder { visit(typed) }.instance + return ESTreeBuilder { visit(typed) }.instance } /** diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 10a6c4a16..1517cdef2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -22,28 +22,20 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp } } + @Suppress("UNUSED_VARIABLE") val instance: Expression by lazy { val node = Program( sourceType = "script", - VariableDeclaration( - kind = "var", - VariableDeclarator( - id = Identifier("executable"), - init = FunctionExpression( - params = arrayOf(Identifier("constants"), Identifier("arguments")), - body = BlockStatement(ReturnStatement(bodyCallback())), - ), - ), - ), + ReturnStatement(bodyCallback()) ) - eval(generate(node)) - GeneratedExpression(js("executable"), constants.toTypedArray()) + val code = generate(node) + GeneratedExpression(js("new Function('constants', 'arguments_0', code)"), constants.toTypedArray()) } private val constants = mutableListOf() - fun constant(value: Any?) = when { + fun constant(value: Any?): BaseExpression = when { value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> SimpleLiteral(value) @@ -61,7 +53,8 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp } } - fun variable(name: Symbol): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name.identity)) + fun variable(name: Symbol): BaseExpression = + call(getOrFail, Identifier("arguments_0"), SimpleLiteral(name.identity)) fun call(function: Function, vararg args: BaseExpression): BaseExpression = SimpleCallExpression( optional = false, diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt index eb5c1e3dd..2434788ec 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt index cca2d83af..cc4360f8d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt index 93b4f6ce6..a17726c9d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt index 86e0cede7..8ea699837 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt index 42b6ac7d8..d907a12c9 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt index 523b13b40..eebfeb6ef 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt index 1f7b09af8..a2a04da79 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt index 3aa31f921..2dd2c08cd 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt @@ -1,8 +1,10 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ +@file:Suppress("unused") + package space.kscience.kmath.internal.estree internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { @@ -28,9 +30,10 @@ internal fun Identifier(name: String) = object : Identifier { override var name = name } -internal fun FunctionExpression(params: Array, body: BlockStatement) = object : FunctionExpression { +internal fun FunctionExpression(id: Identifier?, params: Array, body: BlockStatement) = object : FunctionExpression { override var params = params override var type = "FunctionExpression" + override var id: Identifier? = id override var body = body } diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt index b62b8c06c..bf4a25367 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt index 52be5530f..ced165a3a 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt index 9c012e3a3..2c0dc9de1 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt index 0cd395f2c..f20e2d865 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt index 90690abed..873a5e1d2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index c5023c384..ba86e977b 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index aacb62f36..d29fbde55 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -71,7 +71,7 @@ internal sealed class WasmBuilder>( protected open fun visitBinary(mst: TypedMst.Binary): ExpressionRef = error("Binary operation ${mst.operation} not defined in $this") - protected open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") + protected open fun createModule(): BinaryenModule = space.kscience.kmath.internal.binaryen.Module() protected fun visit(node: TypedMst): ExpressionRef = when (node) { is TypedMst.Constant -> visitNumber( diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt index 21a88b5d0..d60f24247 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index f9540f9db..6a20da799 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt index 0d896c6f6..c6b241e5c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index 8ae5fcb36..0a85d5f24 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 73b9c97a7..59a26af7d 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index a85079fc8..e1fd455fd 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -49,5 +49,7 @@ internal abstract class AsmBuilder { * ASM Type for [space.kscience.kmath.expressions.Symbol]. */ val SYMBOL_TYPE: Type = getObjectType("space/kscience/kmath/expressions/Symbol") + + const val ARGUMENTS_NAME = "args" } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt index 6cf3d8721..acae45d87 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt index 01bad83e5..d50318cd1 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 9e880f4fc..b3ccfdc0c 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt index 3a5ef74f7..6459f4dcf 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ 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 index 556adbe7d..ec66be830 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt index 47f1cc476..9f0fb33ab 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..ec66be830 --- /dev/null +++ b/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2018-2022 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() diff --git a/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt b/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt new file mode 100644 index 000000000..0674b0492 --- /dev/null +++ b/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2018-2022 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 + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) { + //doNothing +} \ No newline at end of file diff --git a/kmath-commons/README.md b/kmath-commons/README.md index 7195e6fb1..89f1f6c9f 100644 --- a/kmath-commons/README.md +++ b/kmath-commons/README.md @@ -6,7 +6,7 @@ Commons math binding for kmath ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-commons:0.3.0' + implementation 'space.kscience:kmath-commons:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-commons:0.3.0") + implementation("space.kscience:kmath-commons:0.3.1-dev-1") } ``` diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 96c17a215..50fef7ac8 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } description = "Commons math binding for kmath" @@ -16,5 +15,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 82694d95a..6d756b15f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt index e0a2f4931..263463d37 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.commons.integration diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 257429fa7..4839518e6 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index aa7e0a638..e95c9115d 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index 9bb5deffd..19799aab3 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt index 11eb6fba8..46baa7d50 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @file:OptIn(UnstableKMathAPI::class) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 194be6002..c7a23ebc4 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index 40168971e..2243dc5d9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 56252ab34..40ba9fc7d 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index c5573fef1..308f504af 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index 0977dc247..b1b7b3ed7 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 4646c6a80..f00952065 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -2,13 +2,13 @@ Complex and hypercomplex number systems in KMath. - - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers - - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions + - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations + - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0' + implementation 'space.kscience:kmath-complex:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0") + implementation("space.kscience:kmath-complex:0.3.1-dev-1") } ``` diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index ea74df646..b63def0a7 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience { + native() } kotlin.sourceSets { @@ -14,18 +16,20 @@ kotlin.sourceSets { readme { description = "Complex numbers and quaternions." - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( id = "complex", - description = "Complex Numbers", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt" - ) + ) { + "Complex numbers operations" + } feature( id = "quaternion", - description = "Quaternions", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt" - ) + ) { + "Quaternions and their composition" + } } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 77fe782a9..5804e47c1 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,10 +10,7 @@ import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MemoryBuffer -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.MutableMemoryBuffer +import space.kscience.kmath.structures.* import kotlin.math.* /** @@ -54,6 +51,9 @@ public object ComplexField : Norm, NumbersAddOps, ScaleOperations { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory { size, init -> + MutableMemoryBuffer.create(Complex, size, init) + } override val zero: Complex = 0.0.toComplex() override val one: Complex = 1.0.toComplex() diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index 46d4b7c5c..42914ed5b 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -56,11 +56,6 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND - get() = bufferAlgebra(Buffer.Companion::complex) - - @OptIn(UnstableKMathAPI::class) public class ComplexFieldND(override val shape: Shape) : ComplexFieldOpsND(), FieldND, diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 3ef3428c6..e9b42118f 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -16,52 +16,137 @@ import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableMemoryBuffer import kotlin.math.* +/** + * Represents `double`-based quaternion. + * + * @property w The first component. + * @property x The second component. + * @property y The third component. + * @property z The fourth component. + */ +public class Quaternion( + public val w: Double, + public val x: Double, + public val y: Double, + public val z: Double, +) : Buffer { + init { + require(!w.isNaN()) { "w-component of quaternion is not-a-number" } + require(!x.isNaN()) { "x-component of quaternion is not-a-number" } + require(!y.isNaN()) { "y-component of quaternion is not-a-number" } + require(!z.isNaN()) { "z-component of quaternion is not-a-number" } + } + + /** + * Returns a string representation of this quaternion. + */ + override fun toString(): String = "($w + $x * i + $y * j + $z * k)" + + override val size: Int get() = 4 + + override fun get(index: Int): Double = when (index) { + 0 -> w + 1 -> x + 2 -> y + 3 -> z + else -> error("Index $index out of bounds [0,3]") + } + + override fun iterator(): Iterator = listOf(w, x, y, z).iterator() + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as Quaternion + + if (w != other.w) return false + if (x != other.x) return false + if (y != other.y) return false + if (z != other.z) return false + + return true + } + + override fun hashCode(): Int { + var result = w.hashCode() + result = 31 * result + x.hashCode() + result = 31 * result + y.hashCode() + result = 31 * result + z.hashCode() + return result + } + + public companion object : MemorySpec { + override val objectSize: Int get() = 32 + + override fun MemoryReader.read(offset: Int): Quaternion = Quaternion( + readDouble(offset), + readDouble(offset + 8), + readDouble(offset + 16), + readDouble(offset + 24) + ) + + override fun MemoryWriter.write(offset: Int, value: Quaternion) { + writeDouble(offset, value.w) + writeDouble(offset + 8, value.x) + writeDouble(offset + 16, value.y) + writeDouble(offset + 24, value.z) + } + } +} + +public fun Quaternion(w: Number, x: Number = 0.0, y: Number = 0.0, z: Number = 0.0): Quaternion = Quaternion( + w.toDouble(), + x.toDouble(), + y.toDouble(), + z.toDouble(), +) + /** * This quaternion's conjugate. */ public val Quaternion.conjugate: Quaternion - get() = QuaternionField { z - x * i - y * j - z * k } + get() = Quaternion(w, -x, -y, -z) /** * This quaternion's reciprocal. */ public val Quaternion.reciprocal: Quaternion get() { - QuaternionField { - val n = norm(this@reciprocal) - return conjugate / (n * n) - } + val norm2 = (w * w + x * x + y * y + z * z) + return Quaternion(w / norm2, -x / norm2, -y / norm2, -z / norm2) } + +//TODO consider adding a-priory normalized quaternions /** - * Absolute value of the quaternion. + * Produce a normalized version of this quaternion */ -public val Quaternion.r: Double - get() = sqrt(w * w + x * x + y * y + z * z) +public fun Quaternion.normalized(): Quaternion = with(QuaternionField){ this@normalized / norm(this@normalized) } /** * A field of [Quaternion]. */ @OptIn(UnstableKMathAPI::class) -public object QuaternionField : Field, Norm, PowerOperations, +public object QuaternionField : Field, Norm, PowerOperations, ExponentialOperations, NumbersAddOps, ScaleOperations { - override val zero: Quaternion = 0.toQuaternion() - override val one: Quaternion = 1.toQuaternion() + override val zero: Quaternion = Quaternion(0.0) + override val one: Quaternion = Quaternion(1.0) /** * The `i` quaternion unit. */ - public val i: Quaternion = Quaternion(0, 1) + public val i: Quaternion = Quaternion(0.0, 1.0, 0.0, 0.0) /** * The `j` quaternion unit. */ - public val j: Quaternion = Quaternion(0, 0, 1) + public val j: Quaternion = Quaternion(0.0, 0.0, 1.0, 0.0) /** * The `k` quaternion unit. */ - public val k: Quaternion = Quaternion(0, 0, 0, 1) + public val k: Quaternion = Quaternion(0.0, 0.0, 0.0, 1.0) override fun add(left: Quaternion, right: Quaternion): Quaternion = Quaternion(left.w + right.w, left.x + right.x, left.y + right.y, left.z + right.z) @@ -133,7 +218,7 @@ public object QuaternionField : Field, Norm, override fun exp(arg: Quaternion): Quaternion { val un = arg.x * arg.x + arg.y * arg.y + arg.z * arg.z - if (un == 0.0) return exp(arg.w).toQuaternion() + if (un == 0.0) return Quaternion(exp(arg.w)) val n1 = sqrt(un) val ea = exp(arg.w) val n2 = ea * sin(n1) / n1 @@ -158,7 +243,8 @@ public object QuaternionField : Field, Norm, return Quaternion(ln(n), th * arg.x, th * arg.y, th * arg.z) } - override operator fun Number.plus(other: Quaternion): Quaternion = Quaternion(toDouble() + other.w, other.x, other.y, other.z) + override operator fun Number.plus(other: Quaternion): Quaternion = + Quaternion(toDouble() + other.w, other.x, other.y, other.z) override operator fun Number.minus(other: Quaternion): Quaternion = Quaternion(toDouble() - other.w, -other.x, -other.y, -other.z) @@ -170,7 +256,12 @@ public object QuaternionField : Field, Norm, Quaternion(toDouble() * arg.w, toDouble() * arg.x, toDouble() * arg.y, toDouble() * arg.z) override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z) - override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg) + override fun norm(arg: Quaternion): Double = sqrt( + arg.w.pow(2) + + arg.x.pow(2) + + arg.y.pow(2) + + arg.z.pow(2) + ) override fun bindSymbolOrNull(value: String): Quaternion? = when (value) { "i" -> i @@ -179,7 +270,7 @@ public object QuaternionField : Field, Norm, else -> null } - override fun number(value: Number): Quaternion = value.toQuaternion() + override fun number(value: Number): Quaternion = Quaternion(value) override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0 override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0 @@ -189,76 +280,6 @@ public object QuaternionField : Field, Norm, override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0 } -/** - * Represents `double`-based quaternion. - * - * @property w The first component. - * @property x The second component. - * @property y The third component. - * @property z The fourth component. - */ -@OptIn(UnstableKMathAPI::class) -public data class Quaternion( - val w: Double, val x: Double, val y: Double, val z: Double, -) { - public constructor(w: Number, x: Number, y: Number, z: Number) : this( - w.toDouble(), - x.toDouble(), - y.toDouble(), - z.toDouble(), - ) - - public constructor(w: Number, x: Number, y: Number) : this(w.toDouble(), x.toDouble(), y.toDouble(), 0.0) - public constructor(w: Number, x: Number) : this(w.toDouble(), x.toDouble(), 0.0, 0.0) - public constructor(w: Number) : this(w.toDouble(), 0.0, 0.0, 0.0) - public constructor(wx: Complex, yz: Complex) : this(wx.re, wx.im, yz.re, yz.im) - public constructor(wx: Complex) : this(wx.re, wx.im, 0, 0) - - init { - require(!w.isNaN()) { "w-component of quaternion is not-a-number" } - require(!x.isNaN()) { "x-component of quaternion is not-a-number" } - require(!y.isNaN()) { "x-component of quaternion is not-a-number" } - require(!z.isNaN()) { "x-component of quaternion is not-a-number" } - } - - /** - * Returns a string representation of this quaternion. - */ - override fun toString(): String = "($w + $x * i + $y * j + $z * k)" - - public companion object : MemorySpec { - override val objectSize: Int - get() = 32 - - override fun MemoryReader.read(offset: Int): Quaternion = - Quaternion(readDouble(offset), readDouble(offset + 8), readDouble(offset + 16), readDouble(offset + 24)) - - override fun MemoryWriter.write(offset: Int, value: Quaternion) { - writeDouble(offset, value.w) - writeDouble(offset + 8, value.x) - writeDouble(offset + 16, value.y) - writeDouble(offset + 24, value.z) - } - } -} - -/** - * Creates a quaternion with real part equal to this real. - * - * @receiver the real part. - * @return a new quaternion. - */ -public fun Number.toQuaternion(): Quaternion = Quaternion(this) - -/** - * Creates a quaternion with `w`-component equal to `re`-component of given complex and `x`-component equal to - * `im`-component of given complex. - * - * @receiver the complex number. - * @return a new quaternion. - */ -public fun Complex.toQuaternion(): Quaternion = Quaternion(this) - /** * Creates a new buffer of quaternions with the specified [size], where each element is calculated by calling the * specified [init] function. diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt index 17a077ea7..ca3f8f43f 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt index cbaaa815b..e11f1c1ea 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt index 7ad7f883d..1a35d1dd8 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 4279471d4..767406e0b 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt similarity index 82% rename from kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt rename to kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt index 6784f3516..fd0fd46a7 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt @@ -1,15 +1,28 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.complex import space.kscience.kmath.operations.invoke +import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test import kotlin.test.assertEquals -internal class QuaternionFieldTest { +internal class QuaternionTest { + + @Test + fun testNorm() { + assertEquals(2.0, QuaternionField.norm(Quaternion(1.0, 1.0, 1.0, 1.0))) + } + + @Test + fun testInverse() = QuaternionField { + val q = Quaternion(1.0, 2.0, -3.0, 4.0) + assertBufferEquals(one, q * q.reciprocal, 1e-4) + } + @Test fun testAddition() { assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(16, 16) + Quaternion(26, 26) }) diff --git a/kmath-core/README.md b/kmath-core/README.md index 4fddd327c..e84ca38d7 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0' + implementation 'space.kscience:kmath-core:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0") + implementation("space.kscience:kmath-core:0.3.1-dev-1") } ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 4a35a54fb..f33d33324 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,8 +1,13 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") -// id("com.xcporter.metaview") version "0.0.5" + id("space.kscience.gradle.mpp") +} + +kscience{ + native() + + dependencies { + api(project(":kmath-memory")) + } } kotlin.sourceSets { @@ -12,23 +17,11 @@ kotlin.sourceSets { it.optIn("space.kscience.kmath.misc.PerformancePitfall") it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } - - commonMain { - dependencies { - api(project(":kmath-memory")) - } - } } -//generateUml { -// classTree { -// -// } -//} - readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index e06b774fd..d09228e96 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index 2fce772cc..a3c3a2eda 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt index 8ddd6406f..dd0e35bc8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt index e99ae0698..3dc1bb99b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt index b5a84cf6c..eecdcebad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt index 3d531349c..10755e633 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt index ee1bebde0..b0803f3e1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt index 485416a69..7d5843a97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index 32a5fc56c..e8b867fac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt new file mode 100644 index 000000000..fa8bf5e58 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt @@ -0,0 +1,456 @@ +/* + * Copyright 2018-2022 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.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.asBuffer +import kotlin.math.max +import kotlin.math.min + +/** + * Class representing both the value and the differentials of a function. + * + * This class is the workhorse of the differentiation package. + * + * This class is an implementation of the extension to Rall's numbers described in Dan Kalman's paper + * [Doubly Recursive Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), + * Mathematics Magazine, vol. 75, no. 3, June 2002. Rall's numbers are an extension to the real numbers used + * throughout mathematical expressions; they hold the derivative together with the value of a function. Dan Kalman's + * derivative structures hold all partial derivatives up to any specified order, with respect to any number of free + * parameters. Rall's numbers therefore can be seen as derivative structures for order one derivative and one free + * parameter, and real numbers can be seen as derivative structures with zero order derivative and no free parameters. + * + * Derived from + * [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java). + */ +@UnstableKMathAPI +public interface DS> { + public val derivativeAlgebra: DSAlgebra + public val data: Buffer +} + +/** + * Get a partial derivative. + * + * @param orders derivation orders with respect to each variable (if all orders are 0, the value is returned). + * @return partial derivative. + * @see value + */ +@UnstableKMathAPI +private fun > DS.getPartialDerivative(vararg orders: Int): T = + data[derivativeAlgebra.compiler.getPartialDerivativeIndex(*orders)] + +/** + * Provide a partial derivative with given symbols. On symbol could me mentioned multiple times + */ +@UnstableKMathAPI +public fun > DS.derivative(symbols: List): T { + require(symbols.size <= derivativeAlgebra.order) { "The order of derivative ${symbols.size} exceeds computed order ${derivativeAlgebra.order}" } + val ordersCount: Map = symbols.map { it.identity }.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*symbols.map { ordersCount[it] ?: 0 }.toIntArray()) +} + +/** + * Provide a partial derivative with given symbols. On symbol could me mentioned multiple times + */ +@UnstableKMathAPI +public fun > DS.derivative(vararg symbols: Symbol): T { + require(symbols.size <= derivativeAlgebra.order) { "The order of derivative ${symbols.size} exceeds computed order ${derivativeAlgebra.order}" } + val ordersCount: Map = symbols.map { it.identity }.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*symbols.map { ordersCount[it] ?: 0 }.toIntArray()) +} + +/** + * The value part of the derivative structure. + * + * @see getPartialDerivative + */ +@UnstableKMathAPI +public val > DS.value: T get() = data[0] + +@UnstableKMathAPI +public abstract class DSAlgebra>( + public val algebra: A, + public val order: Int, + bindings: Map, + public val valueBufferFactory: MutableBufferFactory = algebra.bufferFactory, +) : ExpressionAlgebra>, SymbolIndexer { + + /** + * Get the compiler for number of free parameters and order. + * + * @return cached rules set. + */ + @PublishedApi + internal val compiler: DSCompiler by lazy { + val numberOfVariables = bindings.size + // get the cached compilers + val cache: Array?>>? = null + + // we need to create more compilers + val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) + val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) + val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } + + if (cache != null) { + // preserve the already created compilers + for (i in cache.indices) { + cache[i].copyInto(newCache[i], endIndex = cache[i].size) + } + } + + // create the array in increasing diagonal order + for (diag in 0..numberOfVariables + order) { + for (o in max(0, diag - numberOfVariables)..min(order, diag)) { + val p: Int = diag - o + if (newCache[p][o] == null) { + val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! + val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! + + newCache[p][o] = DSCompiler( + algebra, + valueBufferFactory, + p, + o, + valueCompiler, + derivativeCompiler, + ) + } + } + } + + return@lazy newCache[numberOfVariables][order]!! + } + + private val variables: Map by lazy { + bindings.entries.mapIndexed { index, (key, value) -> + key to DSSymbol( + index, + key, + value, + ) + }.toMap() + } + override val symbols: List = bindings.map { it.key } + + private fun bufferForVariable(index: Int, value: T): Buffer { + val buffer = valueBufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + if (compiler.order > 0) { + // the derivative of the variable with respect to itself is 1. + + val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(symbols.size).apply { + set(index, 1) + }) + + buffer[indexOfDerivative] = algebra.one + } + return buffer + } + + @UnstableKMathAPI + private inner class DSImpl( + override val data: Buffer, + ) : DS { + override val derivativeAlgebra: DSAlgebra get() = this@DSAlgebra + } + + protected fun DS(data: Buffer): DS = DSImpl(data) + + + /** + * Build an instance representing a variable. + * + * Instances built using this constructor are considered to be the free variables with respect to which + * differentials are computed. As such, their differential with respect to themselves is +1. + */ + public fun variable( + index: Int, + value: T, + ): DS { + require(index < compiler.freeParameters) { "number is too large: $index >= ${compiler.freeParameters}" } + return DS(bufferForVariable(index, value)) + } + + /** + * Build an instance from all its derivatives. + * + * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. + */ + public fun ofDerivatives( + vararg derivatives: T, + ): DS { + require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" } + val data = derivatives.asBuffer() + + return DS(data) + } + + /** + * A class implementing both [DS] and [Symbol]. + */ + @UnstableKMathAPI + public inner class DSSymbol internal constructor( + index: Int, + symbol: Symbol, + value: T, + ) : Symbol by symbol, DS { + override val derivativeAlgebra: DSAlgebra get() = this@DSAlgebra + override val data: Buffer = bufferForVariable(index, value) + } + + public override fun const(value: T): DS { + val buffer = valueBufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + + return DS(buffer) + } + + override fun bindSymbolOrNull(value: String): DSSymbol? = variables[StringSymbol(value)] + + override fun bindSymbol(value: String): DSSymbol = + bindSymbolOrNull(value) ?: error("Symbol '$value' is not supported in $this") + + public fun bindSymbolOrNull(symbol: Symbol): DSSymbol? = variables[symbol.identity] + + public fun bindSymbol(symbol: Symbol): DSSymbol = + bindSymbolOrNull(symbol.identity) ?: error("Symbol '${symbol}' is not supported in $this") + + public fun DS.derivative(symbols: List): T { + require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } + val ordersCount = symbols.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*variables.keys.map { ordersCount[it] ?: 0 }.toIntArray()) + } + + public fun DS.derivative(vararg symbols: Symbol): T = derivative(symbols.toList()) + +} + + +/** + * A ring over [DS]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public open class DSRing( + algebra: A, + order: Int, + bindings: Map, + valueBufferFactory: MutableBufferFactory, +) : DSAlgebra(algebra, order, bindings, valueBufferFactory), + Ring>, ScaleOperations>, + NumericAlgebra>, + NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { + + override fun bindSymbolOrNull(value: String): DSSymbol? = + super.bindSymbolOrNull(value) + + override fun DS.unaryMinus(): DS = mapData { -it } + + /** + * Create a copy of given [Buffer] and modify it according to [block] + */ + protected inline fun DS.transformDataBuffer(block: A.(MutableBuffer) -> Unit): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData = valueBufferFactory(compiler.size) { data[it] } + algebra.block(newData) + return DS(newData) + } + + protected fun DS.mapData(block: A.(T) -> T): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData: Buffer = data.map(valueBufferFactory) { + algebra.block(it) + } + return DS(newData) + } + + protected fun DS.mapDataIndexed(block: (Int, T) -> T): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData: Buffer = data.mapIndexed(valueBufferFactory, block) + return DS(newData) + } + + override val zero: DS by lazy { + const(algebra.zero) + } + + override val one: DS by lazy { + const(algebra.one) + } + + override fun number(value: Number): DS = const(algebra.number(value)) + + override fun add(left: DS, right: DS): DS = left.transformDataBuffer { result -> + require(right.derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + compiler.add(left.data, 0, right.data, 0, result, 0) + } + + override fun scale(a: DS, value: Double): DS = a.mapData { + it.times(value) + } + + override fun multiply( + left: DS, + right: DS, + ): DS = left.transformDataBuffer { result -> + compiler.multiply(left.data, 0, right.data, 0, result, 0) + } +// +// override fun DS.minus(arg: DS): DS = transformDataBuffer { result -> +// subtract(data, 0, arg.data, 0, result, 0) +// } + + override operator fun DS.plus(other: Number): DS = transformDataBuffer { + it[0] += number(other) + } + +// +// override operator fun DS.minus(other: Number): DS = +// this + (-other.toDouble()) + + override operator fun Number.plus(other: DS): DS = other + this + override operator fun Number.minus(other: DS): DS = other - this +} + +@UnstableKMathAPI +public class DerivativeStructureRingExpression( + public val algebra: A, + public val elementBufferFactory: MutableBufferFactory = algebra.bufferFactory, + public val function: DSRing.() -> DS, +) : DifferentiableExpression where A : Ring, A : ScaleOperations, A : NumericAlgebra { + override operator fun invoke(arguments: Map): T = + DSRing(algebra, 0, arguments, elementBufferFactory).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + with( + DSRing( + algebra, + symbols.size, + arguments, + elementBufferFactory + ) + ) { function().derivative(symbols) } + } +} + +/** + * A field over commons-math [DerivativeStructure]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public class DSField>( + algebra: A, + order: Int, + bindings: Map, + valueBufferFactory: MutableBufferFactory, +) : DSRing(algebra, order, bindings, valueBufferFactory), ExtendedField> { + override fun number(value: Number): DS = const(algebra.number(value)) + + override fun divide(left: DS, right: DS): DS = left.transformDataBuffer { result -> + compiler.divide(left.data, 0, right.data, 0, result, 0) + } + + override fun sin(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sin(arg.data, 0, result, 0) + } + + override fun cos(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.cos(arg.data, 0, result, 0) + } + + override fun tan(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.tan(arg.data, 0, result, 0) + } + + override fun asin(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.asin(arg.data, 0, result, 0) + } + + override fun acos(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.acos(arg.data, 0, result, 0) + } + + override fun atan(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.atan(arg.data, 0, result, 0) + } + + override fun sinh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sinh(arg.data, 0, result, 0) + } + + override fun cosh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.cosh(arg.data, 0, result, 0) + } + + override fun tanh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.tanh(arg.data, 0, result, 0) + } + + override fun asinh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.asinh(arg.data, 0, result, 0) + } + + override fun acosh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.acosh(arg.data, 0, result, 0) + } + + override fun atanh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.atanh(arg.data, 0, result, 0) + } + + override fun power(arg: DS, pow: Number): DS = when (pow) { + is Int -> arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow, result, 0) + } + else -> arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow.toDouble(), result, 0) + } + } + + override fun sqrt(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sqrt(arg.data, 0, result, 0) + } + + public fun power(arg: DS, pow: DS): DS = arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow.data, 0, result, 0) + } + + override fun exp(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.exp(arg.data, 0, result, 0) + } + + override fun ln(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.ln(arg.data, 0, result, 0) + } +} + +@UnstableKMathAPI +public class DSFieldExpression>( + public val algebra: A, + private val valueBufferFactory: MutableBufferFactory = algebra.bufferFactory, + public val function: DSField.() -> DS, +) : DifferentiableExpression { + override operator fun invoke(arguments: Map): T = + DSField(algebra, 0, arguments, valueBufferFactory).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + DSField( + algebra, + symbols.size, + arguments, + valueBufferFactory, + ).run { function().derivative(symbols) } + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt new file mode 100644 index 000000000..6ab9b3d44 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt @@ -0,0 +1,1487 @@ +/* + * Copyright 2018-2022 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.expressions + + +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory +import kotlin.math.min + +internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: Int = size) { + for (i in fromIndex until toIndex) this[i] = element +} + +/** + * Class holding "compiled" computation rules for derivative structures. + * + * This class implements the computation rules described in Dan Kalman's paper + * [Doubly Recursive Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), + * Mathematics Magazine, vol. 75, no. 3, June 2002. However, to avoid performances bottlenecks, the recursive rules are + * "compiled" once in an unfolded form. This class does this recursion unrolling and stores the computation rules as + * simple loops with pre-computed indirection arrays. + * + * This class maps all derivative computation into single dimension arrays that hold the value and partial derivatives. + * The class does not hold these arrays, which remains under the responsibility of the caller. For each combination of + * number of free parameters and derivation order, only one compiler is necessary, and this compiler will be used to + * perform computations on all arrays provided to it, which can represent hundreds or thousands of different parameters + * kept together with all their partial derivatives. + * + * The arrays on which compilers operate contain only the partial derivatives together with the 0th + * derivative, i.e., the value. The partial derivatives are stored in a compiler-specific order, which can be retrieved + * using methods [getPartialDerivativeIndex] and [getPartialDerivativeOrders]. The value is guaranteed to be stored as + * the first element (i.e., the [getPartialDerivativeIndex] method returns 0 when called with 0 for all derivation + * orders and [getPartialDerivativeOrders] returns an array filled with 0 when called with 0 as the index). + * + * Note that the ordering changes with number of parameters and derivation order. For example given 2 parameters x and + * y, df/dy is stored at index 2 when derivation order is set to 1 (in this case the array has three elements: f, + * df/dx and df/dy). If derivation order is set to 2, then df/dy will be stored at index 3 (in this case the array has + * six elements: f, df/dx, df/dxdx, df/dy, df/dxdy and df/dydy). + * + * Given this structure, users can perform some simple operations like adding, subtracting or multiplying constants and + * negating the elements by themselves, knowing if they want to mutate their array or create a new array. These simple + * operations are not provided by the compiler. The compiler provides only the more complex operations between several + * arrays. + * + * Derived from + * [Commons Math's `DSCompiler`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DSCompiler.java). + * + * @property freeParameters Number of free parameters. + * @property order Derivation order. + * @see DS + */ +public class DSCompiler> internal constructor( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val freeParameters: Int, + public val order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +) { + /** + * Number of partial derivatives (including the single 0 order derivative element). + */ + public val sizes: Array by lazy { + compileSizes( + freeParameters, + order, + valueCompiler, + ) + } + + /** + * Indirection array for partial derivatives. + */ + internal val derivativesIndirection: Array by lazy { + compileDerivativesIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + ) + } + + /** + * Indirection array of the lower derivative elements. + */ + internal val lowerIndirection: IntArray by lazy { + compileLowerIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + ) + } + + /** + * Indirection arrays for multiplication. + */ + internal val multIndirection: Array> by lazy { + compileMultiplicationIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, lowerIndirection, + ) + } + + /** + * Indirection arrays for function composition. + */ + internal val compositionIndirection: Array> by lazy { + compileCompositionIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + sizes, derivativesIndirection, + ) + } + + /** + * Get the array size required for holding partial derivatives' data. + * + * This number includes the single 0 order derivative element, which is + * guaranteed to be stored in the first element of the array. + */ + public val size: Int get() = sizes[freeParameters][order] + + /** + * Get the index of a partial derivative in the array. + * + * If all orders are set to 0, then the 0th order derivative is returned, which is the value of the + * function. + * + * The indices of derivatives are between 0 and [size] − 1. Their specific order is fixed for a given compiler, but + * otherwise not publicly specified. There are however some simple cases which have guaranteed indices: + * + * * the index of 0th order derivative is always 0 + * * if there is only 1 [freeParameters], then the + * derivatives are sorted in increasing derivation order (i.e., f at index 0, df/dp + * at index 1, d2f/dp2 at index 2 … + * dkf/dpk at index k), + * * if the [order] is 1, then the derivatives + * are sorted in increasing free parameter order (i.e., f at index 0, df/dx1 + * at index 1, df/dx2 at index 2 … df/dxk at index k), + * * all other cases are not publicly specified. + * + * This method is the inverse of method [getPartialDerivativeOrders]. + * + * @param orders derivation orders with respect to each parameter. + * @return index of the partial derivative. + * @see getPartialDerivativeOrders + */ + public fun getPartialDerivativeIndex(vararg orders: Int): Int { + // safety check + require(orders.size == freeParameters) { "dimension mismatch: ${orders.size} and $freeParameters" } + return getPartialDerivativeIndex(freeParameters, order, sizes, *orders) + } + + /** + * Get the derivation orders for a specific index in the array. + * + * This method is the inverse of [getPartialDerivativeIndex]. + * + * @param index of the partial derivative + * @return orders derivation orders with respect to each parameter + * @see getPartialDerivativeIndex + */ + public fun getPartialDerivativeOrders(index: Int): IntArray = derivativesIndirection[index] +} + +/** + * Compute natural logarithm of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for logarithm the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.ln( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = ln(operand[operandOffset]) + + if (order > 0) { + val inv = one / operand[operandOffset] + var xk = inv + for (i in 1..order) { + function[i] = xk + xk *= (-i * inv) + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute integer power of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param n power to apply. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + operand: Buffer, + operandOffset: Int, + n: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : PowerOperations = algebra { + if (n == 0) { + // special case, x^0 = 1 for all x + result[resultOffset] = one + result.fill(zero, resultOffset + 1, resultOffset + size) + return + } + + // create the power function value and derivatives + // [x^n, nx^(n-1), n(n-1)x^(n-2), ... ] + val function = bufferFactory(1 + order) { zero } + + if (n > 0) { + // strictly positive power + val maxOrder: Int = min(order, n) + var xk = operand[operandOffset] pow n - maxOrder + for (i in maxOrder downTo 1) { + function[i] = xk + xk *= operand[operandOffset] + } + function[0] = xk + } else { + // strictly negative power + val inv = one / operand[operandOffset] + var xk = inv pow -n + + for (i in 0..order) { + function[i] = xk + xk *= inv + } + } + + var coefficient = number(n) + + for (i in 1..order) { + function[i] = function[i] * coefficient + coefficient *= (n - i).toDouble() + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute exponential of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for exponential the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.exp( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function.fill(exp(operand[operandOffset])) + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute square root of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for nth root the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sqrt( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : PowerOperations = algebra { + // create the function value and derivatives + // [x^(1/n), (1/n)x^((1/n)-1), (1-n)/n^2x^((1/n)-2), ... ] + val function = bufferFactory(1 + order) { zero } + function[0] = sqrt(operand[operandOffset]) + var xk: T = 0.5 * one / function[0] + val xReciprocal = one / operand[operandOffset] + + for (i in 1..order) { + function[i] = xk + xk *= xReciprocal * (0.5 - i) + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.cos( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : TrigonometricOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = cos(operand[operandOffset]) + + if (order > 0) { + function[1] = -sin(operand[operandOffset]) + for (i in 2..order) { + function[i] = -function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute power of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param p power to apply. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + operand: Buffer, + operandOffset: Int, + p: Double, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : NumericAlgebra, A : PowerOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + // [x^p, px^(p-1), p(p-1)x^(p-2), ... ] + val function = bufferFactory(1 + order) { zero } + var xk = operand[operandOffset] pow p - order + + for (i in order downTo 1) { + function[i] = xk + xk *= operand[operandOffset] + } + + function[0] = xk + var coefficient = p + + for (i in 1..order) { + function[i] = function[i] * coefficient + coefficient *= p - i + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for tangent the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.tan( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : TrigonometricOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val t = tan(operand[operandOffset]) + function[0] = t + + if (order > 0) { + + // the nth order derivative of tan has the form: + // dn(tan(x)/dxn = P_n(tan(x)) + // where P_n(t) is a degree n+1 polynomial with same parity as n+1 + // P_0(t) = t, P_1(t) = 1 + t^2, P_2(t) = 2 t (1 + t^2) ... + // the general recurrence relation for P_n is: + // P_n(x) = (1+t^2) P_(n-1)'(t) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order + 2) { zero } + p[1] = one + val t2 = t * t + for (n in 1..order) { + + // update and evaluate polynomial P_n(t) + var v = one + p[n + 1] = n * p[n] + var k = n + 1 + while (k >= 0) { + v = v * t2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (k - 3) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= t + } + function[n] = v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute power of a derivative structure. + * + * @param x array holding the base. + * @param xOffset offset of the base in its array. + * @param y array holding the exponent. + * @param yOffset offset of the exponent in its array. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + x: Buffer, + xOffset: Int, + y: Buffer, + yOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + val logX = bufferFactory(size) { zero } + ln(x, xOffset, logX, 0) + val yLogX = bufferFactory(size) { zero } + multiply(logX, 0, y, yOffset, yLogX, 0) + exp(yLogX, 0, result, resultOffset) +} + +/** + * Compute sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sin( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations, A : TrigonometricOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = sin(operand[operandOffset]) + if (order > 0) { + function[1] = cos(operand[operandOffset]) + for (i in 2..order) { + function[i] = -function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.acos( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = acos(x) + if (order > 0) { + // the nth order derivative of acos has the form: + // dn(acos(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = -1, P_2(x) = -x, P_3(x) = -2x^2 - 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = -one + val x2 = x * x + val f = one / (one - x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + + for (n in 2..order) { + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (n - 1) * p[n - 2] + var k = n - 1 + + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + + if (n and 0x1 == 0) { + v *= x + } + + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.asin( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = asin(x) + if (order > 0) { + // the nth order derivative of asin has the form: + // dn(asin(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = x, P_3(x) = 2x^2 + 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (one - x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (n - 1) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc tangent the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.atan( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : TrigonometricOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = atan(x) + + if (order > 0) { + // the nth order derivative of atan has the form: + // dn(atan(x)/dxn = Q_n(x) / (1 + x^2)^n + // where Q_n(x) is a degree n-1 polynomial with same parity as n-1 + // Q_1(x) = 1, Q_2(x) = -2x, Q_3(x) = 6x^2 - 2 ... + // the general recurrence relation for Q_n is: + // Q_n(x) = (1+x^2) Q_(n-1)'(x) - 2(n-1) x Q_(n-1)(x) + // as per polynomial parity, we can store coefficients of both Q_(n-1) and Q_n in the same array + val q = bufferFactory(order) { zero } + q[0] = one + val x2 = x * x + val f = one / (one + x2) + var coeff = f + function[1] = coeff * q[0] + for (n in 2..order) { + + // update and evaluate polynomial Q_n(x) + var v = zero + q[n - 1] = -n * q[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + q[k] + if (k > 2) { + q[k - 2] = (k - 1) * q[k - 1] + (k - 1 - 2 * n) * q[k - 3] + } else if (k == 2) { + q[0] = q[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute hyperbolic cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for hyperbolic cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.cosh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = cosh(operand[operandOffset]) + + if (order > 0) { + function[1] = sinh(operand[operandOffset]) + for (i in 2..order) { + function[i] = function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute hyperbolic tangent of a derivative structure. + * + * @param operand array holding the operand + * @param operandOffset offset of the operand in its array + * @param result array where result must be stored (for hyperbolic tangent the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.tanh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val t = tanh(operand[operandOffset]) + function[0] = t + if (order > 0) { + + // the nth order derivative of tanh has the form: + // dn(tanh(x)/dxn = P_n(tanh(x)) + // where P_n(t) is a degree n+1 polynomial with same parity as n+1 + // P_0(t) = t, P_1(t) = 1 - t^2, P_2(t) = -2 t (1 - t^2) ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-t^2) P_(n-1)'(t) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order + 2) { zero } + p[1] = one + val t2 = t * t + for (n in 1..order) { + + // update and evaluate polynomial P_n(t) + var v = zero + p[n + 1] = -n * p[n] + var k = n + 1 + while (k >= 0) { + v = v * t2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] - (k - 3) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= t + } + function[n] = v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute inverse hyperbolic cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic cosine the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.acosh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = acosh(x) + + if (order > 0) { + // the nth order derivative of acosh has the form: + // dn(acosh(x)/dxn = P_n(x) / [x^2 - 1]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = -x, P_3(x) = 2x^2 + 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (x^2-1) P_(n-1)'(x) - (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (x2 - one) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (1 - n) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (1 - k) * p[k - 1] + (k - 2 * n) * p[k - 3] + } else if (k == 2) { + p[0] = -p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute composition of a derivative structure by a function. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param f array of value and derivatives of the function at the current point (i.e. at `operand[operandOffset]`). + * @param result array where result must be stored (for composition the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.compose( + operand: Buffer, + operandOffset: Int, + f: Buffer, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations = algebra { + for (i in compositionIndirection.indices) { + val mappingI = compositionIndirection[i] + var r = zero + for (j in mappingI.indices) { + val mappingIJ = mappingI[j] + var product = mappingIJ[0] * f[mappingIJ[1]] + for (k in 2 until mappingIJ.size) { + product *= operand[operandOffset + mappingIJ[k]] + } + r += product + } + result[resultOffset + i] = r + } +} + +/** + * Compute hyperbolic sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for hyperbolic sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sinh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = sinh(operand[operandOffset]) + + if (order > 0) { + function[1] = cosh(operand[operandOffset]) + for (i in 2..order) { + function[i] = function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Perform division of two derivative structures. + * + * @param lhs array holding left-hand side of division. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of division. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (for division the result array *cannot* be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.divide( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : PowerOperations, A : ScaleOperations = algebra { + val reciprocal = bufferFactory(size) { zero } + pow(rhs, lhsOffset, -1, reciprocal, 0) + multiply(lhs, lhsOffset, reciprocal, rhsOffset, result, resultOffset) +} + +/** + * Perform multiplication of two derivative structures. + * + * @param lhs array holding left-hand side of multiplication. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of multiplication. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (for multiplication the result array *cannot* be one of the input + * arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.multiply( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations = algebra { + for (i in multIndirection.indices) { + val mappingI = multIndirection[i] + var r = zero + + for (j in mappingI.indices) { + r += mappingI[j][0] * lhs[lhsOffset + mappingI[j][1]] * rhs[rhsOffset + mappingI[j][2]] + } + + result[resultOffset + i] = r + } +} + +/** + * Perform subtraction of two derivative structures. + * + * @param lhs array holding left-hand side of subtraction. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of subtraction. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (it may be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun > DSCompiler.subtract( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) = algebra { + for (i in 0 until size) { + result[resultOffset + i] = lhs[lhsOffset + i] - rhs[rhsOffset + i] + } +} + +/** + * Compute inverse hyperbolic sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic sine the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.asinh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = asinh(x) + if (order > 0) { + // the nth order derivative of asinh has the form: + // dn(asinh(x)/dxn = P_n(x) / [x^2 + 1]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = -x, P_3(x) = 2x^2 - 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (x^2+1) P_(n-1)'(x) - (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (one + x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (1 - n) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (k - 2 * n) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Perform addition of two derivative structures. + * + * @param lhs array holding left-hand side of addition. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of addition. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (it may be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.add( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Group = algebra { + for (i in 0 until size) { + result[resultOffset + i] = lhs[lhsOffset + i] + rhs[rhsOffset + i] + } +} + +/** + * Check rules set compatibility. + * + * @param compiler other compiler to check against instance. + */ +internal fun > DSCompiler.checkCompatibility(compiler: DSCompiler) { + require(freeParameters == compiler.freeParameters) { + "dimension mismatch: $freeParameters and ${compiler.freeParameters}" + } + require(order == compiler.order) { + "dimension mismatch: $order and ${compiler.order}" + } +} + +/** + * Compute inverse hyperbolic tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic tangent the result array *cannot* be the + * input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.atanh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = atanh(x) + + if (order > 0) { + // the nth order derivative of atanh has the form: + // dn(atanh(x)/dxn = Q_n(x) / (1 - x^2)^n + // where Q_n(x) is a degree n-1 polynomial with same parity as n-1 + // Q_1(x) = 1, Q_2(x) = 2x, Q_3(x) = 6x^2 + 2 ... + // the general recurrence relation for Q_n is: + // Q_n(x) = (1-x^2) Q_(n-1)'(x) + 2(n-1) x Q_(n-1)(x) + // as per polynomial parity, we can store coefficients of both Q_(n-1) and Q_n in the same array + val q = bufferFactory(order) { zero } + q[0] = one + val x2 = x * x + val f = one / (one - x2) + var coeff = f + function[1] = coeff * q[0] + for (n in 2..order) { + + // update and evaluate polynomial Q_n(x) + var v = zero + q[n - 1] = n * q[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + q[k] + if (k > 2) { + q[k - 2] = (k - 1) * q[k - 1] + (2 * n - k + 1) * q[k - 3] + } else if (k == 2) { + q[0] = q[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compile the sizes array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @return sizes array. + */ +private fun > compileSizes( + parameters: Int, order: Int, + valueCompiler: DSCompiler?, +): Array { + val sizes = Array(parameters + 1) { + IntArray(order + 1) + } + + if (parameters == 0) { + sizes[0].fill(1) + } else { + checkNotNull(valueCompiler) + valueCompiler.sizes.copyInto(sizes, endIndex = parameters) + sizes[parameters][0] = 1 + for (i in 0 until order) { + sizes[parameters][i + 1] = sizes[parameters][i] + sizes[parameters - 1][i + 1] + } + } + return sizes +} + +/** + * Compile the derivatives' indirection array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @return derivatives indirection array. + */ +private fun > compileDerivativesIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +): Array { + if (parameters == 0 || order == 0) { + return Array(1) { IntArray(parameters) } + } + + val vSize: Int = valueCompiler!!.derivativesIndirection.size + val dSize: Int = derivativeCompiler!!.derivativesIndirection.size + val derivativesIndirection = Array(vSize + dSize) { IntArray(parameters) } + + // set up the indices for the value part + for (i in 0 until vSize) { + // copy the first indices, the last one remaining set to 0 + valueCompiler.derivativesIndirection[i].copyInto(derivativesIndirection[i], endIndex = parameters - 1) + } + + // set up the indices for the derivative part + for (i in 0 until dSize) { + // copy the indices + derivativeCompiler.derivativesIndirection[i].copyInto(derivativesIndirection[vSize], 0, 0, parameters) + + // increment the derivation order for the last parameter + derivativesIndirection[vSize + i][parameters - 1]++ + } + + return derivativesIndirection +} + +/** + * Compile the lower derivatives' indirection array. + * + * This indirection array contains the indices of all elements except derivatives for last derivation order. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @return lower derivatives' indirection array. + */ +private fun > compileLowerIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +): IntArray { + if (parameters == 0 || order <= 1) return intArrayOf(0) + checkNotNull(valueCompiler) + checkNotNull(derivativeCompiler) + + // this is an implementation of definition 6 in Dan Kalman's paper. + val vSize: Int = valueCompiler.lowerIndirection.size + val dSize: Int = derivativeCompiler.lowerIndirection.size + val lowerIndirection = IntArray(vSize + dSize) + valueCompiler.lowerIndirection.copyInto(lowerIndirection, endIndex = vSize) + for (i in 0 until dSize) { + lowerIndirection[vSize + i] = valueCompiler.size + derivativeCompiler.lowerIndirection[i] + } + return lowerIndirection +} + +/** + * Compile the multiplication indirection array. + * + * This indirection array contains the indices of all pairs of elements involved when computing a multiplication. This + * allows a straightforward loop-based multiplication (see [multiply]). + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @param lowerIndirection lower derivatives' indirection array. + * @return multiplication indirection array. + */ +@Suppress("UNCHECKED_CAST") +private fun > compileMultiplicationIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, + lowerIndirection: IntArray, +): Array> { + if (parameters == 0 || order == 0) return arrayOf(arrayOf(intArrayOf(1, 0, 0))) + + // this is an implementation of definition 3 in Dan Kalman's paper. + val vSize = valueCompiler!!.multIndirection.size + val dSize = derivativeCompiler!!.multIndirection.size + val multIndirection: Array?> = arrayOfNulls(vSize + dSize) + valueCompiler.multIndirection.copyInto(multIndirection, endIndex = vSize) + + for (i in 0 until dSize) { + val dRow = derivativeCompiler.multIndirection[i] + val row: List = buildList(dRow.size * 2) { + for (j in dRow.indices) { + add(intArrayOf(dRow[j][0], lowerIndirection[dRow[j][1]], vSize + dRow[j][2])) + add(intArrayOf(dRow[j][0], vSize + dRow[j][1], lowerIndirection[dRow[j][2]])) + } + } + + // combine terms with similar derivation orders + val combined: List = buildList(row.size) { + for (j in row.indices) { + val termJ = row[j] + if (termJ[0] > 0) { + for (k in j + 1 until row.size) { + val termK = row[k] + + if (termJ[1] == termK[1] && termJ[2] == termK[2]) { + // combine termJ and termK + termJ[0] += termK[0] + // make sure we will skip termK later on in the outer loop + termK[0] = 0 + } + } + + add(termJ) + } + } + } + + multIndirection[vSize + i] = combined.toTypedArray() + } + + return multIndirection as Array> +} + +/** + * Compile the indirection array of function composition. + * + * This indirection array contains the indices of all sets of elements involved when computing a composition. This + * allows a straightforward loop-based composition (see [compose]). + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @param sizes sizes array. + * @param derivativesIndirection derivatives indirection array. + * @return multiplication indirection array. + */ +@Suppress("UNCHECKED_CAST") +private fun > compileCompositionIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, + sizes: Array, + derivativesIndirection: Array, +): Array> { + if (parameters == 0 || order == 0) { + return arrayOf(arrayOf(intArrayOf(1, 0))) + } + + val vSize = valueCompiler!!.compositionIndirection.size + val dSize = derivativeCompiler!!.compositionIndirection.size + val compIndirection: Array?> = arrayOfNulls(vSize + dSize) + + // the composition rules from the value part can be reused as is + valueCompiler.compositionIndirection.copyInto(compIndirection, endIndex = vSize) + + // the composition rules for the derivative part are deduced by differentiation the rules from the + // underlying compiler once with respect to the parameter this compiler handles and the underlying one + // did not handle + + // the composition rules for the derivative part are deduced by differentiation the rules from the + // underlying compiler once with respect to the parameter this compiler handles and the underlying one did + // not handle + for (i in 0 until dSize) { + val row: List = buildList { + for (term in derivativeCompiler.compositionIndirection[i]) { + + // handle term p * f_k(g(x)) * g_l1(x) * g_l2(x) * ... * g_lp(x) + + // derive the first factor in the term: f_k with respect to new parameter + val derivedTermF = IntArray(term.size + 1) + derivedTermF[0] = term[0] // p + derivedTermF[1] = term[1] + 1 // f_(k+1) + val orders = IntArray(parameters) + orders[parameters - 1] = 1 + derivedTermF[term.size] = getPartialDerivativeIndex( + parameters, + order, + sizes, + *orders + ) // g_1 + + for (j in 2 until term.size) { + // convert the indices as the mapping for the current order is different from the mapping with one + // less order + derivedTermF[j] = convertIndex( + term[j], parameters, + derivativeCompiler.derivativesIndirection, + parameters, order, sizes + ) + } + + derivedTermF.sort(2, derivedTermF.size) + add(derivedTermF) + + // derive the various g_l + for (l in 2 until term.size) { + val derivedTermG = IntArray(term.size) + derivedTermG[0] = term[0] + derivedTermG[1] = term[1] + + for (j in 2 until term.size) { + // convert the indices as the mapping for the current order + // is different from the mapping with one less order + derivedTermG[j] = convertIndex( + term[j], + parameters, + derivativeCompiler.derivativesIndirection, + parameters, + order, + sizes, + ) + + if (j == l) { + // derive this term + derivativesIndirection[derivedTermG[j]].copyInto(orders, endIndex = parameters) + orders[parameters - 1]++ + + derivedTermG[j] = getPartialDerivativeIndex( + parameters, + order, + sizes, + *orders, + ) + } + } + + derivedTermG.sort(2, derivedTermG.size) + add(derivedTermG) + } + } + } + + // combine terms with similar derivation orders + val combined: List = buildList(row.size) { + for (j in row.indices) { + val termJ = row[j] + + if (termJ[0] > 0) { + (j + 1 until row.size).map { k -> row[k] }.forEach { termK -> + var equals = termJ.size == termK.size + var l = 1 + + while (equals && l < termJ.size) { + equals = equals and (termJ[l] == termK[l]) + ++l + } + + if (equals) { + // combine termJ and termK + termJ[0] += termK[0] + // make sure we will skip termK later on in the outer loop + termK[0] = 0 + } + } + + add(termJ) + } + } + } + + compIndirection[vSize + i] = combined.toTypedArray() + } + + return compIndirection as Array> +} + +/** + * Get the index of a partial derivative in an array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param sizes sizes array. + * @param orders derivation orders with respect to each parameter (the length of this array must match the number of + * parameters). + * @return index of the partial derivative. + */ +private fun getPartialDerivativeIndex( + parameters: Int, + order: Int, + sizes: Array, + vararg orders: Int, +): Int { + + // the value is obtained by diving into the recursive Dan Kalman's structure + // this is theorem 2 of his paper, with recursion replaced by iteration + var index = 0 + var m = order + var ordersSum = 0 + + for (i in parameters - 1 downTo 0) { + // derivative order for current free parameter + var derivativeOrder = orders[i] + + // safety check + ordersSum += derivativeOrder + require(ordersSum <= order) { "number is too large: $ordersSum > $order" } + + while (derivativeOrder-- > 0) { + // as long as we differentiate according to current free parameter, + // we have to skip the value part and dive into the derivative part, + // so we add the size of the value part to the base index + index += sizes[i][m--] + } + } + + return index +} + +/** + * Convert an index from one (parameters, order) structure to another. + * + * @param index index of a partial derivative in source derivative structure. + * @param srcP number of free parameters in source derivative structure. + * @param srcDerivativesIndirection derivatives indirection array for the source derivative structure. + * @param destP number of free parameters in destination derivative structure. + * @param destO derivation order in destination derivative structure. + * @param destSizes sizes array for the destination derivative structure. + * @return index of the partial derivative with the *same* characteristics in destination derivative structure. + */ +private fun convertIndex( + index: Int, + srcP: Int, + srcDerivativesIndirection: Array, + destP: Int, + destO: Int, + destSizes: Array, +): Int { + val orders = IntArray(destP) + srcDerivativesIndirection[index].copyInto(orders, endIndex = min(srcP, destP)) + return getPartialDerivativeIndex(destP, destO, destSizes, *orders) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 12b7df0ea..7c8a957c7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 5ba32f190..9c769caa0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 68cc8e791..1054d1aa1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt index 18226119b..9705a3f03 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 4bd2a6c53..a75940cca 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index ac8c44446..f00e6d3f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt index 8ab2bec31..c57ce69ab 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index bf37e9615..e5f92efc9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt index 907ce4004..8cfa1b353 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 36cbd9064..361d59be1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,13 +11,12 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.asND import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.indices public class BufferedLinearSpace>( - private val bufferAlgebra: BufferAlgebra + private val bufferAlgebra: BufferAlgebra, ) : LinearSpace { override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra @@ -91,5 +90,5 @@ public class BufferedLinearSpace>( } -public fun > A.linearSpace(bufferFactory: BufferFactory): BufferedLinearSpace = - BufferedLinearSpace(BufferRingOps(this, bufferFactory)) +public val > A.linearSpace: BufferedLinearSpace + get() = BufferedLinearSpace(BufferRingOps(this)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt index 4e6debc60..e2f81d84e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index fae9e7c91..af9ebb463 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 715fad07b..757752115 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,12 +11,9 @@ import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.as1D import space.kscience.kmath.operations.BufferRingOps -import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass /** @@ -187,18 +184,9 @@ public interface LinearSpace> { * A structured matrix with custom buffer */ public fun > buffered( - algebra: A, - bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): LinearSpace = BufferedLinearSpace(BufferRingOps(algebra, bufferFactory)) + algebra: A + ): LinearSpace = BufferedLinearSpace(BufferRingOps(algebra)) - @Deprecated("use DoubleField.linearSpace") - public val double: LinearSpace = buffered(DoubleField, ::DoubleBuffer) - - /** - * Automatic buffered matrix, unboxed if it is possible - */ - public inline fun > auto(ring: A): LinearSpace = - buffered(ring, Buffer.Companion::auto) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index fb57f2343..0ee7c8828 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 029612bc5..d0105e4cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt index b70e9d8a9..ce7acdcba 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index b1812f49d..feea26b40 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index fb2b1e547..eb5e20856 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt index 29b7caec6..a752a8339 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 7c612b6a9..f7b486850 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -27,5 +27,5 @@ public annotation class UnstableKMathAPI RequiresOptIn.Level.WARNING, ) public annotation class PerformancePitfall( - val message: String = "Potential performance problem" + val message: String = "Potential performance problem", ) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index ee7f1d8be..c05f1a6a9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -7,6 +7,7 @@ package space.kscience.kmath.misc import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer import kotlin.jvm.JvmName /** @@ -42,8 +43,8 @@ public inline fun List.cumulative(initial: R, crossinline operation: ( /** * Cumulative sum with custom space */ -public fun Iterable.cumulativeSum(group: Ring): Iterable = - group { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Iterable.cumulativeSum(ring: Ring): Iterable = + ring { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Iterable.cumulativeSum(): Iterable = cumulative(0.0) { element, sum -> sum + element } @@ -54,8 +55,8 @@ public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -public fun Sequence.cumulativeSum(group: Ring): Sequence = - group { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Sequence.cumulativeSum(ring: Ring): Sequence = + ring { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Sequence.cumulativeSum(): Sequence = cumulative(0.0) { element, sum -> sum + element } @@ -77,3 +78,12 @@ public fun List.cumulativeSum(): List = cumulative(0) { element, sum - @JvmName("cumulativeSumOfLong") public fun List.cumulativeSum(): List = cumulative(0L) { element, sum -> sum + element } + + +public fun Buffer.cumulativeSum(ring: Ring): Buffer = with(ring) { + var accumulator: T = zero + return bufferFactory(size) { + accumulator += get(it) + accumulator + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt index 9dfc564c3..c7886469f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt index f879a06d5..77ef07ea8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt index dc5421136..daf5e1eff 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt @@ -1,6 +1,6 @@ /* - * 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 file. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index a9712e870..101f90160 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,25 +10,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass -/** - * An exception is thrown when the expected and actual shape of NDArray differ. - * - * @property expected the expected shape. - * @property actual the actual shape. - */ -public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : - RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") - -public typealias Shape = IntArray - -public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(shapeFirst, *shapeRest) - -public interface WithShape { - public val shape: Shape - - public val indices: ShapeIndexer get() = DefaultStrides(shape) -} - /** * The base interface for all ND-algebra implementations. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index b09344d12..4025ba548 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,6 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.BufferFactory public interface BufferAlgebraND> : AlgebraND { public val indexerBuilder: (IntArray) -> ShapeIndexer @@ -47,7 +46,7 @@ public interface BufferAlgebraND> : AlgebraND { zipInline(left.toBufferND(), right.toBufferND(), transform) public companion object { - public val defaultIndexerBuilder: (IntArray) -> ShapeIndexer = DefaultStrides.Companion::invoke + public val defaultIndexerBuilder: (IntArray) -> ShapeIndexer = ::Strides } } @@ -60,7 +59,7 @@ public inline fun > BufferAlgebraND.mapInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(buffer.size) { elementAlgebra.transform(buffer[it]) } + elementBufferFactory(buffer.size) { elementAlgebra.transform(buffer[it]) } } ) } @@ -74,7 +73,7 @@ internal inline fun > BufferAlgebraND.mapIndexedInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(buffer.size) { elementAlgebra.transform(indexes.index(it), buffer[it]) } + elementBufferFactory(buffer.size) { elementAlgebra.transform(indexes.index(it), buffer[it]) } } ) } @@ -91,7 +90,7 @@ internal inline fun > BufferAlgebraND.zipInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(lbuffer.size) { elementAlgebra.block(lbuffer[it], rbuffer[it]) } + elementBufferFactory(lbuffer.size) { elementAlgebra.block(lbuffer[it], rbuffer[it]) } } ) } @@ -116,9 +115,8 @@ public open class BufferedFieldOpsND>( public constructor( elementAlgebra: A, - bufferFactory: BufferFactory, indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, - ) : this(BufferFieldOps(elementAlgebra, bufferFactory), indexerBuilder) + ) : this(BufferFieldOps(elementAlgebra), indexerBuilder) @OptIn(PerformancePitfall::class) override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 2401f6319..1eb08fa8c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -56,7 +56,7 @@ public inline fun StructureND.mapToBuffer( * @param strides The strides to access elements of [MutableBuffer] by linear indices. * @param buffer The underlying buffer. */ -public class MutableBufferND( +public open class MutableBufferND( strides: ShapeIndexer, override val buffer: MutableBuffer, ) : MutableStructureND, BufferND(strides, buffer) { @@ -69,7 +69,7 @@ public class MutableBufferND( * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] */ public inline fun MutableStructureND.mapToMutableBuffer( - factory: MutableBufferFactory = MutableBuffer.Companion::auto, + factory: MutableBufferFactory = MutableBufferFactory(MutableBuffer.Companion::auto), crossinline transform: (T) -> R, ): MutableBufferND { return if (this is MutableBufferND) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index d01a8ee95..aab137321 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,12 +11,13 @@ import space.kscience.kmath.operations.* import space.kscience.kmath.structures.DoubleBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.math.pow import kotlin.math.pow as kpow public class DoubleBufferND( indexes: ShapeIndexer, override val buffer: DoubleBuffer, -) : BufferND(indexes, buffer) +) : MutableBufferND(indexes, buffer) public sealed class DoubleFieldOpsND : BufferedFieldOpsND(DoubleField.bufferAlgebra), @@ -165,6 +166,15 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D override fun atanh(arg: StructureND): DoubleBufferND = mapInline(arg.toBufferND()) { kotlin.math.atanh(it) } + override fun power( + arg: StructureND, + pow: Number, + ): StructureND = if (pow is Int) { + mapInline(arg.toBufferND()) { it.pow(pow) } + } else { + mapInline(arg.toBufferND()) { it.pow(pow.toDouble()) } + } + public companion object : DoubleFieldOpsND() } @@ -181,7 +191,7 @@ public class DoubleFieldND(override val shape: Shape) : it.kpow(pow) } - override fun power(arg: StructureND, pow: Number): DoubleBufferND = if(pow.isInteger()){ + override fun power(arg: StructureND, pow: Number): DoubleBufferND = if (pow.isInteger()) { power(arg, pow.toInt()) } else { val dpow = pow.toDouble() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt new file mode 100644 index 000000000..ac01239a9 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2018-2022 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.nd + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.NumbersAddOps +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.structures.IntBuffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +public class IntBufferND( + indexes: ShapeIndexer, + override val buffer: IntBuffer, +) : MutableBufferND(indexes, buffer) + +public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.bufferAlgebra) { + + override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntBufferND { + val indexer = indexerBuilder(shape) + return IntBufferND( + indexer, + IntBuffer(indexer.linearSize) { offset -> + elementAlgebra.initializer(indexer.index(offset)) + } + ) + } + + public companion object : IntRingOpsND() +} + +@OptIn(UnstableKMathAPI::class) +public class IntRingND( + override val shape: Shape +) : IntRingOpsND(), RingND, NumbersAddOps> { + + override fun number(value: Number): BufferND { + val int = value.toInt() // minimize conversions + return structureND(shape) { int } + } +} + +public inline fun IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return IntRingND(shape).run(action) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt new file mode 100644 index 000000000..c5d04c9de --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2022 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.nd + +/** + * An exception is thrown when the expected and actual shape of NDArray differ. + * + * @property expected the expected shape. + * @property actual the actual shape. + */ +public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : + RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") + +public class IndexOutOfShapeException(public val shape: Shape, public val index: IntArray) : + RuntimeException("Index ${index.contentToString()} is out of shape ${shape.contentToString()}") + +public typealias Shape = IntArray + +public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(shapeFirst, *shapeRest) + +public interface WithShape { + public val shape: Shape + + public val indices: ShapeIndexer get() = DefaultStrides(shape) +} + +internal fun requireIndexInShape(index: IntArray, shape: Shape) { + if (index.size != shape.size) throw IndexOutOfShapeException(index, shape) + shape.forEachIndexed { axis, axisShape -> + if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(index, shape) + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt index c6ff79587..2dce407ca 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,7 @@ import kotlin.native.concurrent.ThreadLocal /** * A converter from linear index to multivariate index */ -public interface ShapeIndexer: Iterable{ +public interface ShapeIndexer : Iterable { public val shape: Shape /** @@ -44,7 +44,7 @@ public interface ShapeIndexer: Iterable{ /** * Linear transformation of indexes */ -public abstract class Strides: ShapeIndexer { +public abstract class Strides : ShapeIndexer { /** * Array strides */ @@ -66,7 +66,7 @@ public abstract class Strides: ShapeIndexer { /** * Simple implementation of [Strides]. */ -public class DefaultStrides private constructor(override val shape: IntArray) : Strides() { +public class DefaultStrides(override val shape: IntArray) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -112,10 +112,16 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Cached builder for default strides */ + @Deprecated("Replace by Strides(shape)") public operator fun invoke(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } } } @ThreadLocal -private val defaultStridesCache = HashMap() \ No newline at end of file +private val defaultStridesCache = HashMap() + +/** + * Cached builder for default strides + */ +public fun Strides(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index 8152adaa5..249b6801d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -22,8 +22,9 @@ public class ShortRingND( ) : ShortRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { - val d = value.toShort() // minimize conversions - return structureND(shape) { d } + val short + = value.toShort() // minimize conversions + return structureND(shape) { short } } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 4ccb15eef..2a258a7f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index cf8559869..d8fd2031c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -138,6 +138,10 @@ private class MutableStructure2DWrapper(val structure: MutableStructureND) override fun equals(other: Any?): Boolean = false override fun hashCode(): Int = 0 + + override fun toString(): String { + return StructureND.toString(structure) + } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index d948cf36f..b2da083bb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -82,7 +82,7 @@ public interface StructureND : Featured, WithShape { public fun contentEquals( st1: StructureND, st2: StructureND, - tolerance: Double = 1e-11 + tolerance: Double = 1e-11, ): Boolean { if (st1 === st2) return true @@ -101,11 +101,17 @@ public interface StructureND : Featured, WithShape { val bufferRepr: String = when (structure.shape.size) { 1 -> (0 until structure.shape[0]).map { structure[it] } .joinToString(prefix = "[", postfix = "]", separator = ", ") - 2 -> (0 until structure.shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i -> - (0 until structure.shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j -> + + 2 -> (0 until structure.shape[0]).joinToString( + prefix = "[\n", + postfix = "\n]", + separator = ",\n" + ) { i -> + (0 until structure.shape[1]).joinToString(prefix = " [", postfix = "]", separator = ", ") { j -> structure[i, j].toString() } } + else -> "..." } val className = structure::class.simpleName ?: "StructureND" @@ -120,7 +126,7 @@ public interface StructureND : Featured, WithShape { */ public fun buffered( strides: Strides, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) @@ -140,7 +146,7 @@ public interface StructureND : Featured, WithShape { public fun buffered( shape: IntArray, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = buffered(DefaultStrides(shape), bufferFactory, initializer) @@ -227,16 +233,8 @@ public interface MutableStructureND : StructureND { } /** - * Transform a structure element-by element in place. + * Set value at specified indices */ -@OptIn(PerformancePitfall::class) -public inline fun MutableStructureND.mapInPlace(action: (index: IntArray, t: T) -> T): Unit = - elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } - -public inline fun StructureND.zip( - struct: StructureND, - crossinline block: (T, T) -> T, -): StructureND { - require(shape.contentEquals(struct.shape)) { "Shape mismatch in structure combination" } - return StructureND.auto(shape) { block(this[it], struct[it]) } -} +public operator fun MutableStructureND.set(vararg index: Int, value: T) { + set(index, value) +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt new file mode 100644 index 000000000..579a0d7c8 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2018-2022 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.nd + +import space.kscience.kmath.misc.UnstableKMathAPI + +public open class VirtualStructureND( + override val shape: Shape, + public val producer: (IntArray) -> T, +) : StructureND { + override fun get(index: IntArray): T { + requireIndexInShape(index, shape) + return producer(index) + } +} + +@UnstableKMathAPI +public class VirtualDoubleStructureND( + shape: Shape, + producer: (IntArray) -> Double, +) : VirtualStructureND(shape, producer) + +@UnstableKMathAPI +public class VirtualIntStructureND( + shape: Shape, + producer: (IntArray) -> Int, +) : VirtualStructureND(shape, producer) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt index 53f946fbd..1b7bd20db 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt new file mode 100644 index 000000000..5814e2f9c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2018-2022 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.nd + +public fun StructureND.roll(axis: Int, step: Int = 1): StructureND { + require(axis in shape.indices) { "Axis $axis is outside of shape dimensions: [0, ${shape.size})" } + return VirtualStructureND(shape) { index -> + val newIndex: IntArray = IntArray(index.size) { indexAxis -> + if (indexAxis == axis) { + (index[indexAxis] + step).mod(shape[indexAxis]) + } else { + index[indexAxis] + } + } + get(newIndex) + } +} + +public fun StructureND.roll(pair: Pair, vararg others: Pair): StructureND { + val axisMap: Map = mapOf(pair, *others) + require(axisMap.keys.all { it in shape.indices }) { "Some of axes ${axisMap.keys} is outside of shape dimensions: [0, ${shape.size})" } + return VirtualStructureND(shape) { index -> + val newIndex: IntArray = IntArray(index.size) { indexAxis -> + val offset = axisMap[indexAxis] ?: 0 + (index[indexAxis] + offset).mod(shape[indexAxis]) + } + get(newIndex) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 45ba32c13..a7a5bc5fd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -8,12 +8,7 @@ package space.kscience.kmath.operations import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring.Companion.optimizedPower - -/** - * Stub for DSL the [Algebra] is. - */ -@DslMarker -public annotation class KMathContext +import space.kscience.kmath.structures.MutableBufferFactory /** * Represents an algebraic structure. @@ -21,6 +16,12 @@ public annotation class KMathContext * @param T the type of element of this structure. */ public interface Algebra { + + /** + * Provide a factory for buffers, associated with this [Algebra] + */ + public val bufferFactory: MutableBufferFactory get() = MutableBufferFactory.boxing() + /** * Wraps a raw string to [T] object. This method is designed for three purposes: * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 99268348b..8730ff163 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,6 @@ import space.kscience.kmath.nd.BufferedRingOpsND import space.kscience.kmath.operations.BigInt.Companion.BASE import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MutableBuffer import kotlin.math.log2 import kotlin.math.max import kotlin.math.min @@ -528,19 +527,11 @@ public fun String.parseBigInteger(): BigInt? { public val BigInt.algebra: BigIntField get() = BigIntField -@Deprecated("Use BigInt::buffer") -public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = - boxing(size, initializer) - public inline fun BigInt.Companion.buffer(size: Int, initializer: (Int) -> BigInt): Buffer = Buffer.boxing(size, initializer) -@Deprecated("Use BigInt::mutableBuffer") -public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer = - boxing(size, initializer) - -public inline fun BigInt.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer = +public inline fun BigInt.Companion.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer = Buffer.boxing(size, initializer) public val BigIntField.nd: BufferedRingOpsND - get() = BufferedRingOpsND(BufferRingOps(BigIntField, BigInt::buffer)) + get() = BufferedRingOpsND(BufferRingOps(BigIntField)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt index 51fff8b69..af0bc4d9b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -7,8 +7,6 @@ package space.kscience.kmath.operations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.ShortBuffer public interface WithSize { public val size: Int @@ -19,11 +17,11 @@ public interface WithSize { */ public interface BufferAlgebra> : Algebra> { public val elementAlgebra: A - public val bufferFactory: BufferFactory + public val elementBufferFactory: BufferFactory get() = elementAlgebra.bufferFactory public fun buffer(size: Int, vararg elements: T): Buffer { require(elements.size == size) { "Expected $size elements but found ${elements.size}" } - return bufferFactory(size) { elements[it] } + return elementBufferFactory(size) { elements[it] } } //TODO move to multi-receiver inline extension @@ -36,13 +34,13 @@ public interface BufferAlgebra> : Algebra> { override fun unaryOperationFunction(operation: String): (arg: Buffer) -> Buffer { val operationFunction = elementAlgebra.unaryOperationFunction(operation) - return { arg -> bufferFactory(arg.size) { operationFunction(arg[it]) } } + return { arg -> elementBufferFactory(arg.size) { operationFunction(arg[it]) } } } override fun binaryOperationFunction(operation: String): (left: Buffer, right: Buffer) -> Buffer { val operationFunction = elementAlgebra.binaryOperationFunction(operation) return { left, right -> - bufferFactory(left.size) { operationFunction(left[it], right[it]) } + elementBufferFactory(left.size) { operationFunction(left[it], right[it]) } } } } @@ -53,7 +51,7 @@ public interface BufferAlgebra> : Algebra> { private inline fun > BufferAlgebra.mapInline( buffer: Buffer, crossinline block: A.(T) -> T, -): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) } +): Buffer = elementBufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) } /** * Inline map @@ -61,7 +59,7 @@ private inline fun > BufferAlgebra.mapInline( private inline fun > BufferAlgebra.mapIndexedInline( buffer: Buffer, crossinline block: A.(index: Int, arg: T) -> T, -): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) } +): Buffer = elementBufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) } /** * Inline zip @@ -72,15 +70,15 @@ private inline fun > BufferAlgebra.zipInline( crossinline block: A.(l: T, r: T) -> T, ): Buffer { require(l.size == r.size) { "Incompatible buffer sizes. left: ${l.size}, right: ${r.size}" } - return bufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) } + return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) } } public fun BufferAlgebra.buffer(size: Int, initializer: (Int) -> T): Buffer { - return bufferFactory(size, initializer) + return elementBufferFactory(size, initializer) } public fun A.buffer(initializer: (Int) -> T): Buffer where A : BufferAlgebra, A : WithSize { - return bufferFactory(size, initializer) + return elementBufferFactory(size, initializer) } public fun > BufferAlgebra.sin(arg: Buffer): Buffer = @@ -131,7 +129,6 @@ public fun > BufferAlgebra.pow(arg: Buffer, p public open class BufferRingOps>( override val elementAlgebra: A, - override val bufferFactory: BufferFactory, ) : BufferAlgebra, RingOps> { override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } @@ -145,16 +142,17 @@ public open class BufferRingOps>( super.binaryOperationFunction(operation) } +public val IntRing.bufferAlgebra: BufferRingOps + get() = BufferRingOps(IntRing) + public val ShortRing.bufferAlgebra: BufferRingOps - get() = BufferRingOps(ShortRing, ::ShortBuffer) + get() = BufferRingOps(ShortRing) public open class BufferFieldOps>( elementAlgebra: A, - bufferFactory: BufferFactory, -) : BufferRingOps(elementAlgebra, bufferFactory), BufferAlgebra, FieldOps>, - ScaleOperations> { +) : BufferRingOps(elementAlgebra), BufferAlgebra, FieldOps>, ScaleOperations> { -// override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } + // override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } // override fun multiply(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l * r } override fun divide(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l / r } @@ -167,30 +165,26 @@ public open class BufferFieldOps>( public class BufferField>( elementAlgebra: A, - bufferFactory: BufferFactory, override val size: Int, -) : BufferFieldOps(elementAlgebra, bufferFactory), Field>, WithSize { +) : BufferFieldOps(elementAlgebra), Field>, WithSize { - override val zero: Buffer = bufferFactory(size) { elementAlgebra.zero } - override val one: Buffer = bufferFactory(size) { elementAlgebra.one } + override val zero: Buffer = elementAlgebra.bufferFactory(size) { elementAlgebra.zero } + override val one: Buffer = elementAlgebra.bufferFactory(size) { elementAlgebra.one } } /** * Generate full buffer field from given buffer operations */ public fun > BufferFieldOps.withSize(size: Int): BufferField = - BufferField(elementAlgebra, bufferFactory, size) + BufferField(elementAlgebra, size) //Double buffer specialization public fun BufferField.buffer(vararg elements: Number): Buffer { require(elements.size == size) { "Expected $size elements but found ${elements.size}" } - return bufferFactory(size) { elements[it].toDouble() } + return elementBufferFactory(size) { elements[it].toDouble() } } -public fun > A.bufferAlgebra(bufferFactory: BufferFactory): BufferFieldOps = - BufferFieldOps(this, bufferFactory) - -public val DoubleField.bufferAlgebra: BufferFieldOps - get() = BufferFieldOps(DoubleField, ::DoubleBuffer) +public val > A.bufferAlgebra: BufferFieldOps + get() = BufferFieldOps(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt index f2f7326aa..449730e7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt index 0ee591acc..ded8753a3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt @@ -1,17 +1,15 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.operations import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.asBuffer - import kotlin.math.* /** @@ -21,7 +19,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte Norm, Double> { override val elementAlgebra: DoubleField get() = DoubleField - override val bufferFactory: BufferFactory get() = ::DoubleBuffer + override val elementBufferFactory: MutableBufferFactory get() = elementAlgebra.bufferFactory override fun Buffer.map(block: DoubleField.(Double) -> Double): DoubleBuffer = mapInline { DoubleField.block(it) } @@ -135,6 +133,12 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte override fun scale(a: Buffer, value: Double): DoubleBuffer = a.mapInline { it * value } + override fun power(arg: Buffer, pow: Number): Buffer = if (pow is Int) { + arg.mapInline { it.pow(pow) } + } else { + arg.mapInline { it.pow(pow.toDouble()) } + } + public companion object : DoubleBufferOps() { public inline fun Buffer.mapInline(block: (Double) -> Double): DoubleBuffer = if (this is DoubleBuffer) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt index 9037525e1..5cf98c7d5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index d0405c705..5c2747686 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 709506fc4..c24394add 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 539440de9..efadfb3cc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt index 31b0c2841..3d25d8750 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -61,43 +61,60 @@ public inline fun Buffer.toTypedArray(): Array = Array(size, : /** * Create a new buffer from this one with the given mapping function and using [Buffer.Companion.auto] buffer factory. */ -public inline fun Buffer.map(block: (T) -> R): Buffer = +public inline fun Buffer.map(block: (T) -> R): Buffer = Buffer.auto(size) { block(get(it)) } /** * Create a new buffer from this one with the given mapping function. * Provided [bufferFactory] is used to construct the new buffer. */ -public inline fun Buffer.map( +public inline fun Buffer.map( bufferFactory: BufferFactory, crossinline block: (T) -> R, ): Buffer = bufferFactory(size) { block(get(it)) } /** - * Create a new buffer from this one with the given indexed mapping function. - * Provided [BufferFactory] is used to construct the new buffer. + * Create a new buffer from this one with the given mapping (indexed) function. + * Provided [bufferFactory] is used to construct the new buffer. */ -public inline fun Buffer.mapIndexed( - bufferFactory: BufferFactory = Buffer.Companion::auto, +public inline fun Buffer.mapIndexed( + bufferFactory: BufferFactory, crossinline block: (index: Int, value: T) -> R, ): Buffer = bufferFactory(size) { block(it, get(it)) } +/** + * Create a new buffer from this one with the given indexed mapping function. + * Provided [BufferFactory] is used to construct the new buffer. + */ +public inline fun Buffer.mapIndexed( + crossinline block: (index: Int, value: T) -> R, +): Buffer = Buffer.auto(size) { block(it, get(it)) } + /** * Fold given buffer according to [operation] */ -public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R): R { +public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R): R { var accumulator = initial for (index in this.indices) accumulator = operation(accumulator, get(index)) return accumulator } +/** + * Fold given buffer according to indexed [operation] + */ +public inline fun Buffer.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R { + var accumulator = initial + for (index in this.indices) accumulator = operation(index, accumulator, get(index)) + return accumulator +} + /** * Zip two buffers using given [transform]. */ @UnstableKMathAPI -public inline fun Buffer.zip( +public inline fun Buffer.zip( other: Buffer, - bufferFactory: BufferFactory = Buffer.Companion::auto, + bufferFactory: BufferFactory = BufferFactory.auto(), crossinline transform: (T1, T2) -> R, ): Buffer { require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 07a137415..224ca1daf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -1,12 +1,14 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ - +@file:Suppress("NOTHING_TO_INLINE") package space.kscience.kmath.operations +import space.kscience.kmath.structures.* import kotlin.math.pow as kpow + /** * Advanced Number-like semifield that implements basic operations. */ @@ -14,7 +16,8 @@ public interface ExtendedFieldOps : FieldOps, TrigonometricOperations, ExponentialOperations, - ScaleOperations { + ScaleOperations, + PowerOperations { override fun tan(arg: T): T = sin(arg) / cos(arg) override fun tanh(arg: T): T = sinh(arg) / cosh(arg) @@ -40,7 +43,7 @@ public interface ExtendedFieldOps : /** * Advanced Number-like field that implements basic operations. */ -public interface ExtendedField : ExtendedFieldOps, Field, PowerOperations, NumericAlgebra { +public interface ExtendedField : ExtendedFieldOps, Field, NumericAlgebra { override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0 override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0 override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) @@ -63,8 +66,10 @@ public interface ExtendedField : ExtendedFieldOps, Field, PowerOperatio /** * 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") public object DoubleField : ExtendedField, Norm, ScaleOperations { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::DoubleBuffer) + override inline val zero: Double get() = 0.0 override inline val one: Double get() = 1.0 @@ -121,8 +126,10 @@ public val Double.Companion.algebra: DoubleField get() = DoubleField /** * A field for [Float] 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") public object FloatField : ExtendedField, Norm { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::FloatBuffer) + override inline val zero: Float get() = 0.0f override inline val one: Float get() = 1.0f @@ -175,13 +182,12 @@ public val Float.Companion.algebra: FloatField get() = FloatField /** * A field for [Int] without boxing. Does not produce corresponding ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object IntRing : Ring, Norm, NumericAlgebra { - override inline val zero: Int - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::IntBuffer) - override inline val one: Int - get() = 1 + override inline val zero: Int get() = 0 + override inline val one: Int get() = 1 override fun number(value: Number): Int = value.toInt() override inline fun add(left: Int, right: Int): Int = left + right @@ -199,13 +205,12 @@ public val Int.Companion.algebra: IntRing get() = IntRing /** * A field for [Short] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object ShortRing : Ring, Norm, NumericAlgebra { - override inline val zero: Short - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ShortBuffer) - override inline val one: Short - get() = 1 + override inline val zero: Short get() = 0 + override inline val one: Short get() = 1 override fun number(value: Number): Short = value.toShort() override inline fun add(left: Short, right: Short): Short = (left + right).toShort() @@ -223,13 +228,12 @@ public val Short.Companion.algebra: ShortRing get() = ShortRing /** * A field for [Byte] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object ByteRing : Ring, Norm, NumericAlgebra { - override inline val zero: Byte - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ByteBuffer) - override inline val one: Byte - get() = 1 + override inline val zero: Byte get() = 0 + override inline val one: Byte get() = 1 override fun number(value: Number): Byte = value.toByte() override inline fun add(left: Byte, right: Byte): Byte = (left + right).toByte() @@ -247,13 +251,12 @@ public val Byte.Companion.algebra: ByteRing get() = ByteRing /** * A field for [Double] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object LongRing : Ring, Norm, NumericAlgebra { - override inline val zero: Long - get() = 0L + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::LongBuffer) - override inline val one: Long - get() = 1L + override inline val zero: Long get() = 0L + override inline val one: Long get() = 1L override fun number(value: Number): Long = value.toLong() override inline fun add(left: Long, right: Long): Long = left + right diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt index 3528b0460..8e81dd941 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index a1b0307c4..5cfafe5a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -14,14 +14,34 @@ import kotlin.reflect.KClass * * @param T the type of buffer. */ -public typealias BufferFactory = (Int, (Int) -> T) -> Buffer +public fun interface BufferFactory { + public operator fun invoke(size: Int, builder: (Int) -> T): Buffer + + public companion object{ + public inline fun auto(): BufferFactory = + BufferFactory(Buffer.Companion::auto) + + public fun boxing(): BufferFactory = + BufferFactory(Buffer.Companion::boxing) + } +} /** * Function that produces [MutableBuffer] from its size and function that supplies values. * * @param T the type of buffer. */ -public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer +public fun interface MutableBufferFactory : BufferFactory { + override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer + + public companion object { + public inline fun auto(): MutableBufferFactory = + MutableBufferFactory(MutableBuffer.Companion::auto) + + public fun boxing(): MutableBufferFactory = + MutableBufferFactory(MutableBuffer.Companion::boxing) + } +} /** * A generic read-only random-access structure for both primitives and objects. @@ -94,7 +114,6 @@ public interface Buffer { * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ - @Suppress("UNCHECKED_CAST") public inline fun auto(size: Int, initializer: (Int) -> T): Buffer = auto(T::class, size, initializer) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index 4d04a5235..07355d396 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt new file mode 100644 index 000000000..2be17c5e4 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2022 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.structures + +import kotlin.jvm.JvmInline + +/** + * Specialized [MutableBuffer] implementation over [ByteArray]. + * + * @property array the underlying array. + */ +@JvmInline +public value class ByteBuffer(public val array: ByteArray) : MutableBuffer { + override val size: Int get() = array.size + + override operator fun get(index: Int): Byte = array[index] + + override operator fun set(index: Int, value: Byte) { + array[index] = value + } + + override operator fun iterator(): ByteIterator = array.iterator() + override fun copy(): MutableBuffer = ByteBuffer(array.copyOf()) +} + +/** + * Creates a new [ByteBuffer] with the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for a buffer element given its index. + */ +public inline fun ByteBuffer(size: Int, init: (Int) -> Byte): ByteBuffer = ByteBuffer(ByteArray(size) { init(it) }) + +/** + * Returns a new [ByteBuffer] of given elements. + */ +public fun ByteBuffer(vararg bytes: Byte): ByteBuffer = ByteBuffer(bytes) + +/** + * Returns a new [ByteArray] containing all the elements of this [Buffer]. + */ +public fun Buffer.toByteArray(): ByteArray = when (this) { + is ByteBuffer -> array.copyOf() + else -> ByteArray(size, ::get) +} + +/** + * Returns [ByteBuffer] over this array. + * + * @receiver the array. + * @return the new buffer. + */ +public fun ByteArray.asBuffer(): ByteBuffer = ByteBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt index f4388a477..4dd9003f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -47,11 +47,6 @@ public inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = */ public fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(doubles) -/** - * Simplified [DoubleBuffer] to array comparison - */ -public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) - /** * Returns a new [DoubleArray] containing all the elements of this [Buffer]. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt index b3c537280..d99e02996 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index e7e98fc71..8666ca675 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index 35b722e2b..f80ad0ff7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -24,8 +24,7 @@ public value class IntBuffer(public val array: IntArray) : MutableBuffer { override operator fun iterator(): IntIterator = array.iterator() - override fun copy(): MutableBuffer = - IntBuffer(array.copyOf()) + override fun copy(): IntBuffer = IntBuffer(array.copyOf()) } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt index 65d9dc77d..fbc9a489b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index c69f4646d..9d6f1b2a7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt index 1dadaf7d4..80d5033c4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt index 429c1a64b..709ebd680 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index 20691511b..7dbb2b58e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt new file mode 100644 index 000000000..f46f3023d --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:OptIn(UnstableKMathAPI::class) + +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFails + +internal inline fun diff( + order: Int, + vararg parameters: Pair, + block: DSField.() -> Unit, +) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + DSField(DoubleField, order, mapOf(*parameters), ::DoubleBuffer).block() +} + +internal class DSTest { + private val x by symbol + private val y by symbol + + @Test + fun dsAlgebraTest() { + diff(2, x to 1.0, y to 1.0) { + val x = bindSymbol(x)//by binding() + val y = bindSymbol("y") + val z = x * (-sin(x * y) + y) + 2.0 + println(z.derivative(x)) + println(z.derivative(y, x)) + assertEquals(z.derivative(x, y), z.derivative(y, x)) + // check improper order cause failure + assertFails { z.derivative(x, x, y) } + } + } + + @Test + fun dsExpressionTest() { + val f = DSFieldExpression(DoubleField, ::DoubleBuffer) { + val x by binding + val y by binding + x.pow(2) + 2 * x * y + y.pow(2) + 1 + } + + assertEquals(10.0, f(x to 1.0, y to 2.0)) + assertEquals(6.0, f.derivative(x)(x to 1.0, y to 2.0)) + assertEquals(2.0, f.derivative(x, x)(x to 1.234, y to -2.0)) + assertEquals(2.0, f.derivative(x, y)(x to 1.0, y to 2.0)) + } +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index 80c5943cf..def9f91a6 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index 156334b2e..6f207eab3 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index 201890933..1618296be 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index 70e010f2e..25e29f3d6 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 25d187bf0..fe5ea3642 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt index e5f3f337f..811f2e87f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt index 4a724ac5f..4f3469ea2 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt @@ -1,6 +1,6 @@ /* - * 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 file. + * Copyright 2018-2022 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.misc diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt new file mode 100644 index 000000000..e909a2aea --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2018-2022 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.nd + +import space.kscience.kmath.operations.DoubleField +import kotlin.test.Test +import kotlin.test.assertEquals + +class NdOperationsTest { + @Test + fun roll() { + val structure = DoubleField.ndAlgebra.structureND(5, 5) { index -> + index.sumOf { it.toDouble() } + } + + println(StructureND.toString(structure)) + + val rolled = structure.roll(0,-1) + + println(StructureND.toString(rolled)) + + assertEquals(4.0, rolled[0, 0]) + } + +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 0527f5252..f4f7b1a51 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt index eec3dc3bf..786c68c70 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index 85f368f3e..36f00dc75 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt index 26d6af224..8a6116605 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt index 76171fedd..688daa7fe 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt index b7b89d107..566145621 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index d33eb5112..a54af571e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -74,7 +74,9 @@ class NumberNDFieldTest { @Test fun combineTest() { - val division = array1.zip(array2, Double::div) + algebra { + val division = zip(array1, array2) { l, r -> l / r } + } } object L2Norm : Norm, Double> { diff --git a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt index 68a3c995b..e52ea9298 100644 --- a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt index 24b81322e..3103f5168 100644 --- a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt index 5ba0dbc9b..3780ea1ae 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt index 6e22c2381..584748bd7 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt index b2f9b957b..9868daddf 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt index 68a3c995b..e52ea9298 100644 --- a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt index b2f9b957b..9868daddf 100644 --- a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/README.md b/kmath-coroutines/README.md index d0fef6e0f..337d8e037 100644 --- a/kmath-coroutines/README.md +++ b/kmath-coroutines/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-coroutines:0.3.0' + implementation 'space.kscience:kmath-coroutines:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-coroutines:0.3.0") + implementation("space.kscience:kmath-coroutines:0.3.1-dev-1") } ``` diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index aa30c412b..529084619 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.sourceSets { @@ -17,11 +19,11 @@ kotlin.sourceSets { dependencies { api(project(":kmath-core")) api(project(":kmath-complex")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}") + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${space.kscience.gradle.KScienceVersions.coroutinesVersion}") } } } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt index 87aebff61..2e9a15eed 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index 25e20291e..797d2db4a 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt index ac0327d0b..a481156f2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index 994255e38..ed0283630 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 7bf54d50f..77d4203c5 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt index 1f17efe49..3f06693b0 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt index 4d4493aa4..00c874751 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt index abe1c9df9..2ac8c1eb4 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt index dd6e39071..a62bcc6b8 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index ac9eb773a..786d32190 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -18,12 +18,12 @@ public class LazyStructureND( ) : StructureND { private val cache: MutableMap> = HashMap() - public fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { + public fun async(index: IntArray): Deferred = cache.getOrPut(index) { scope.async(context = Dispatchers.Math) { function(index) } } - public suspend fun await(index: IntArray): T = deferred(index).await() - override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() } + public suspend fun await(index: IntArray): T = async(index).await() + override operator fun get(index: IntArray): T = runBlocking { async(index).await() } @OptIn(PerformancePitfall::class) override fun elements(): Sequence> { @@ -33,8 +33,8 @@ public class LazyStructureND( } } -public fun StructureND.deferred(index: IntArray): Deferred = - if (this is LazyStructureND) deferred(index) else CompletableDeferred(get(index)) +public fun StructureND.async(index: IntArray): Deferred = + if (this is LazyStructureND) this@async.async(index) else CompletableDeferred(get(index)) public suspend fun StructureND.await(index: IntArray): T = if (this is LazyStructureND) await(index) else get(index) diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt index 9b67f7253..c448168e3 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt index 305b97e5d..a6d7f006c 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/README.md b/kmath-dimensions/README.md index 650bcafde..12aa2a7fa 100644 --- a/kmath-dimensions/README.md +++ b/kmath-dimensions/README.md @@ -6,7 +6,7 @@ A proof of concept module for adding type-safe dimensions to structures ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-dimensions:0.3.0' + implementation 'space.kscience:kmath-dimensions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-dimensions:0.3.0") + implementation("space.kscience:kmath-dimensions:0.3.1-dev-1") } ``` diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 885f3c227..29c0eccb6 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } description = "A proof of concept module for adding type-safe dimensions to structures" @@ -21,5 +23,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index e57c22834..14677319c 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index f04536f04..b93114804 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt index 59260fe73..e2793855b 100644 --- a/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 610e8b4c0..1ae484228 100644 --- a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index e6d8b3b35..24cfb14e8 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 64edbe935..f5f749c8a 100644 --- a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index eaa90120f..2d6c661e4 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0' + implementation 'space.kscience:kmath-ejml:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0") + implementation("space.kscience:kmath-ejml:0.3.1-dev-1") } ``` diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 727d21e3a..d7f780d79 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,8 +1,7 @@ import space.kscience.kmath.ejml.codegen.ejmlCodegen plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } dependencies { @@ -14,7 +13,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 32030dfe3..beb79fc0e 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 27fd3fc53..1d70c0e7d 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index 37995c27e..c4fae9951 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index dce739dc2..aac327a84 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -271,7 +271,9 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -505,7 +507,9 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -734,7 +738,9 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -963,7 +969,9 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 209bb5b27..e3bff8987 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -1,8 +1,10 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ +@file:OptIn(PerformancePitfall::class) + package space.kscience.kmath.ejml import org.ejml.data.DMatrixRMaj @@ -18,11 +20,11 @@ import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* -@OptIn(PerformancePitfall::class) -fun assertMatrixEquals(expected: StructureND, actual: StructureND) { +internal fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } +@OptIn(UnstableKMathAPI::class) internal class EjmlMatrixTest { private val random = Random(0) diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index 9592bfa6c..7d3ea314b 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 9e8f95a16..5a8376976 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0' + implementation 'space.kscience:kmath-for-real:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0") + implementation("space.kscience:kmath-for-real:0.3.1-dev-1") } ``` diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 18c2c50ad..1e964d99c 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,12 +1,14 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") } -kotlin.sourceSets.commonMain { +kscience { + native() dependencies { - api(project(":kmath-core")) + api(projects.kmathCore) + } + dependencies("commonTest") { + implementation(projects.testUtils) } } @@ -16,27 +18,27 @@ readme { All operations are specialized to work with `Double` numbers without declaring algebraic contexts. One can still use generic algebras though. """.trimIndent() - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( id = "DoubleVector", ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt" - ){ + ) { "Numpy-like operations for Buffers/Points" } feature( id = "DoubleMatrix", ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt" - ){ + ) { "Numpy-like operations for 2d real structures" } feature( id = "grids", ref = "src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt" - ){ + ) { "Uniform grid generators" } } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt index 7b9740c35..e607786fb 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 671e272ab..c44b1dff0 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index dc5c58be0..0c18602f1 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 1926ef02c..6403cf509 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt index 52362f4b4..2c06b76b7 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt index 4a0e8de1d..0d016116d 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,7 +11,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.algebra -import space.kscience.kmath.structures.contentEquals +import space.kscience.kmath.testutils.contentEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt index e77b96c12..a25091ac2 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt index 8fed8d10e..31be9a452 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 3f44bd3f9..1292424b5 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0' + implementation 'space.kscience:kmath-functions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0") + implementation("space.kscience:kmath-functions:0.3.1-dev-1") } ``` diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index fadbac091..2e7b023c1 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,19 +1,27 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } description = "Functions, integration and interpolation" -kotlin.sourceSets.commonMain { - dependencies { - api(project(":kmath-core")) +kotlin.sourceSets { + commonMain { + dependencies { + api(project(":kmath-core")) + } } } +dependencies { + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${npmlibs.versions.dokka.get()}") +} + readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt") { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 16af7f555..a9f51f7b0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index a36d36f52..af84f47f2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,132 +1,280 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") + package space.kscience.kmath.functions -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations +import space.kscience.kmath.operations.invoke import kotlin.math.max -import kotlin.math.pow +import kotlin.math.min + /** - * Polynomial coefficients model without fixation on specific context they are applied to. + * Represents univariate polynomial that stores its coefficients in a [List]. * - * @param coefficients constant is the leftmost coefficient. + * @param C the type of constants. */ -public class Polynomial(public val coefficients: List) { +public data class Polynomial( + /** + * List that contains coefficients of the polynomial. + * + * Every monomial \(a x^d\) is stored as a coefficient \(a\) placed + * into the list at index \(d\). For example, coefficients of a polynomial \(5 x^2 - 6\) can be represented as + * ``` + * listOf( + * -6, // -6 + + * 0, // 0 x + + * 5, // 5 x^2 + * ) + * ``` + * and also as + * ``` + * listOf( + * -6, // -6 + + * 0, // 0 x + + * 5, // 5 x^2 + * 0, // 0 x^3 + * 0, // 0 x^4 + * ) + * ``` + * It is not prohibited to put extra zeros at end of the list (as for \(0x^3\) and \(0x^4\) in the example). But the + * longer the coefficients list the worse performance of arithmetical operations performed on it. Thus, it is + * recommended not to put (or even to remove) extra (or useless) coefficients at the end of the coefficients list. + * + * @usesMathJax + */ + public val coefficients: List +) { override fun toString(): String = "Polynomial$coefficients" } /** - * Returns a [Polynomial] instance with given [coefficients]. - */ -@Suppress("FunctionName") -public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun Polynomial.value(arg: Double): Double = coefficients.reduceIndexed { index, acc, c -> - acc + c * arg.pow(index) -} - -/** - * Evaluates the value of the given polynomial for given argument. - * https://en.wikipedia.org/wiki/Horner%27s_method - */ -public fun > Polynomial.value(ring: C, arg: T): T = ring { - if (coefficients.isEmpty()) return@ring zero - var result: T = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } - -/** - * Create a polynomial witch represents differentiated version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.differentiate( - algebra: A, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) -} - -/** - * Create a polynomial witch represents indefinite integral version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.integrate( - algebra: A, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - val integratedCoefficients = buildList(coefficients.size + 1) { - add(zero) - coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } - } - Polynomial(integratedCoefficients) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > Polynomial.integrate( - algebra: Field, - range: ClosedRange, -): T = algebra { - val integral = integrate(algebra) - integral.value(algebra, range.endInclusive) - integral.value(algebra, range.start) -} - -/** - * Space of polynomials. + * Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the provided + * [ring] of constants. * - * @param T the type of operated polynomials. - * @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T]. - * @param ring the [C] instance. + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. */ -public class PolynomialSpace( - private val ring: C, -) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { - override val zero: Polynomial = Polynomial(emptyList()) - - override fun Polynomial.unaryMinus(): Polynomial = ring { - Polynomial(coefficients.map { -it }) - } - - override fun add(left: Polynomial, right: Polynomial): Polynomial { - val dim = max(left.coefficients.size, right.coefficients.size) - - return ring { - Polynomial(List(dim) { index -> - left.coefficients.getOrElse(index) { zero } + right.coefficients.getOrElse(index) { zero } - }) - } - } - - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } +public open class PolynomialSpace( + /** + * Underlying ring of constants. Its operations on constants are used by local operations on constants and polynomials. + */ + public val ring: A, +) : Ring>, ScaleOperations> where A : Ring, A : ScaleOperations { /** - * Evaluates the polynomial for the given value [arg]. + * Instance of zero constant (zero of the underlying ring). */ - public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) + public val constantZero: C get() = ring.zero + /** + * Instance of unit constant (unit of the underlying ring). + */ + public val constantOne: C get() = ring.one - public fun Polynomial.asFunction(): (T) -> T = asFunction(ring) + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public operator fun C.plus(other: Polynomial): Polynomial = + with(ring) { + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@plus)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) this@plus else this@plus + get(0) -} - -public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return PolynomialSpace(this).block() + if (size == 0) add(result) + else this[0] = result + } + ) + } + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public operator fun C.minus(other: Polynomial): Polynomial = + with(ring) { + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@minus)) + else Polynomial( + toMutableList() + .apply { + (1..lastIndex).forEach { this[it] = -this[it] } + + val result = if (size == 0) this@minus else this@minus - get(0) + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + public operator fun C.times(other: Polynomial): Polynomial = + with(ring) { + Polynomial( + other.coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + } + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public operator fun Polynomial.plus(other: C): Polynomial = + with(ring) { + with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) + other + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public operator fun Polynomial.minus(other: C): Polynomial = + with(ring) { + with(coefficients) { + if (isEmpty()) Polynomial(listOf(-other)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) - other + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + public operator fun Polynomial.times(other: C): Polynomial = + with(ring) { + Polynomial( + coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this[deg] * other + } + ) + } + + /** + * Converts the constant [value] to polynomial. + */ + public fun number(value: C): Polynomial = Polynomial(listOf(value)) + /** + * Converts the constant to polynomial. + */ + public fun C.asPolynomial(): Polynomial = number(this) + + /** + * Returns negation of the polynomial. + */ + public override operator fun Polynomial.unaryMinus(): Polynomial = ring { + Polynomial(coefficients.map { -it }) + } + /** + * Returns sum of the polynomials. + */ + public override operator fun Polynomial.plus(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] + } + } + ) + } + /** + * Returns difference of the polynomials. + */ + public override operator fun Polynomial.minus(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> -other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] + } + } + ) + } + /** + * Returns product of the polynomials. + */ + public override operator fun Polynomial.times(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) + } + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: Polynomial = Polynomial(emptyList()) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: Polynomial by lazy { Polynomial(listOf(constantOne)) } + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public val Polynomial.degree: Int get() = coefficients.lastIndex + + override fun add(left: Polynomial, right: Polynomial): Polynomial = left + right + override fun multiply(left: Polynomial, right: Polynomial): Polynomial = left * right + override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(a.coefficients.map { scale(it, value) }) } + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline fun Polynomial.substitute(argument: C): C = value(ring, argument) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun Polynomial.asFunction(): (C) -> C = asFunctionOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline operator fun Polynomial.invoke(argument: C): C = value(ring, argument) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt index 0e814993c..c2f95f040 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt new file mode 100644 index 000000000..4e9791a87 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2018-2022 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.functions + + +/** + * Constructs a [Polynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else this }) + +/** + * Constructs a [Polynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +/** + * Represents [this] constant as a [Polynomial]. + */ +public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt new file mode 100644 index 000000000..5effe566a --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.math.max +import kotlin.math.pow + + +/** + * Creates a [PolynomialSpace] over a received ring. + */ +public inline val A.polynomialSpace: PolynomialSpace where A : Ring, A : ScaleOperations + get() = PolynomialSpace(this) + +/** + * Creates a [PolynomialSpace]'s scope over a received ring. + */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] +public inline fun A.polynomialSpace(block: PolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return PolynomialSpace(this).block() +} + + +/** + * Evaluates value of [this] Double polynomial on provided Double argument. + */ +public fun Polynomial.value(arg: Double): Double = + coefficients.reduceIndexedOrNull { index, acc, c -> + acc + c * arg.pow(index) + } ?: .0 + +/** + * Evaluates value of [this] polynomial on provided argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun Polynomial.value(ring: Ring, arg: C): C = ring { + if (coefficients.isEmpty()) return zero + var result: C = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > Polynomial.asFunctionOver(ring: A): (C) -> C = { value(ring, it) } + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.differentiate( + ring: A, +): Polynomial where A : Ring, A : NumericAlgebra = ring { + Polynomial( + buildList(max(0, coefficients.size - 1)) { + for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.integrate( + ring: A, +): Polynomial where A : Field, A : NumericAlgebra = ring { + Polynomial( + buildList(coefficients.size + 1) { + add(zero) + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } + } + ) +} + +/** + * Computes a definite integral of [this] polynomial in the specified [range]. + */ +@UnstableKMathAPI +public fun > Polynomial.integrate( + ring: Field, + range: ClosedRange, +): C = ring { + val antiderivative = integrate(ring) + return antiderivative.value(ring, range.endInclusive) - antiderivative.value(ring, range.start) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 9785d7744..603f0503a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.integration diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 778d85e66..4cfed8efe 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index 05e2e5c55..40fe78898 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt index 1cf15b42f..18c46b83b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt index 96b81aaa6..53a563086 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 7815757aa..7e4ff0f8b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index eb88d9ae0..9a8f475c8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 6fd75e6e6..af8c858fa 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 2266092a3..52e8991b1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 34d7bcf41..49d7fd1ca 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index afcb33bd4..a63142be4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 05c16d17e..3051cdd8d 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -1,17 +1,303 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ +@file:Suppress("LocalVariableName") + package space.kscience.kmath.functions -import kotlin.test.Test -import kotlin.test.assertEquals +import space.kscience.kmath.functions.testUtils.* +import kotlin.test.* + class PolynomialTest { @Test - fun testIntegration() { - val polynomial = Polynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.value(1.0), 0.001) + fun test_Polynomial_Constant_plus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial() + Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Polynomial(Rational(-2)) + Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Polynomial() + Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial() - Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Polynomial(Rational(2)) - Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Polynomial() - Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).polynomialSpace { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + Polynomial(22, 26, 13, 15, 26) * m(27), + "test 1" + ) + assertEquals( + Polynomial(0, 0, 0, 0, 0), + Polynomial(7, 0, 49, 21, 14) * m(15), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(-3) + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(2) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(2) + Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(0) + Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Rational(1) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Rational(1) + Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Rational(2) + Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(3) - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(-2) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(-2) - Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(0) - Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Rational(-1) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Rational(-1) - Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Rational(-2) - Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).polynomialSpace { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + m(27) * Polynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + Polynomial(0, 0, 0, 0, 0), + m(15) * Polynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.polynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 + assertEquals( + Polynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) + + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 + assertEquals( + Polynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + + Polynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.polynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 + assertEquals( + Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) - + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 + assertEquals( + Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).polynomialSpace { + // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 + assertEquals( + Polynomial(1, 0, 1, 0, 1), + Polynomial(1, -1, 1) * Polynomial(1, 1, 1), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + Polynomial(0, 0, 0, 0, 0), + Polynomial(5, -25, 10) * Polynomial(21, 14, -7), + "test 2" + ) + } } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt new file mode 100644 index 000000000..c1b1008ae --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.test.Test +import kotlin.test.assertEquals + + +@OptIn(UnstableKMathAPI::class) +class PolynomialUtilTest { + @Test + fun test_Polynomial_value_Double() { + assertEquals( + 0.0, + Polynomial(1.0, -2.0, 1.0).value(1.0), + 0.001, + "test 1" + ) + assertEquals( + 0.0, + Polynomial(1.0, -2.0, 1.0).value(1.0), + 0.001, + "test 1" + ) + assertEquals( + 1.1931904761904761, + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).value(0.2), + 0.001, + "test 2" + ) + assertEquals( + 0.5681904761904762, + Polynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).value(0.2), + 0.001, + "test 3" + ) + assertEquals( + 1.1811904761904761, + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).value(0.2), + 0.001, + "test 4" + ) + assertEquals( + 1.1703333333333332, + Polynomial(0.625, 2.6666666666666665, 0.0, 1.5).value(0.2), + 0.001, + "test 5" + ) + } + @Test + fun test_Polynomial_value_Constant() { + assertEquals( + Rational(0), + Polynomial(Rational(1), Rational(-2), Rational(1)).value(RationalField, Rational(1)), + "test 1" + ) + assertEquals( + Rational(25057, 21000), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .value(RationalField, Rational(1, 5)), + "test 2" + ) + assertEquals( + Rational(2983, 5250), + Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .value(RationalField, Rational(1, 5)), + "test 3" + ) + assertEquals( + Rational(4961, 4200), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0)) + .value(RationalField, Rational(1, 5)), + "test 4" + ) + assertEquals( + Rational(3511, 3000), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2)) + .value(RationalField, Rational(1, 5)), + "test 5" + ) + } + @Test + fun test_Polynomial_differentiate() { + assertEquals( + Polynomial(Rational(-2), Rational(2)), + Polynomial(Rational(1), Rational(-2), Rational(1)).differentiate(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).differentiate(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).differentiate(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).differentiate(RationalField), + "test 4" + ) + } + @Test + fun test_Polynomial_integrate() { + assertEquals( + Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + Polynomial(Rational(1), Rational(-2), Rational(1)).integrate(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).integrate(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).integrate(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).integrate(RationalField), + "test 4" + ) + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt new file mode 100644 index 000000000..3b7409e82 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations + + +class IntModulo { + val residue: Int + val modulus: Int + + @PublishedApi + internal constructor(residue: Int, modulus: Int, toCheckInput: Boolean = true) { + if (toCheckInput) { + require(modulus != 0) { "modulus can not be zero" } + this.modulus = if (modulus < 0) -modulus else modulus + this.residue = residue.mod(this.modulus) + } else { + this.residue = residue + this.modulus = modulus + } + } + + constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + + operator fun unaryPlus(): IntModulo = this + operator fun unaryMinus(): IntModulo = + IntModulo( + if (residue == 0) 0 else modulus - residue, + modulus, + toCheckInput = false + ) + operator fun plus(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not add two residue different modulo" } + return IntModulo( + (residue + other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun plus(other: Int): IntModulo = + IntModulo( + (residue + other) % modulus, + modulus, + toCheckInput = false + ) + operator fun minus(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not subtract two residue different modulo" } + return IntModulo( + (residue - other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun minus(other: Int): IntModulo = + IntModulo( + (residue - other) % modulus, + modulus, + toCheckInput = false + ) + operator fun times(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not multiply two residue different modulo" } + return IntModulo( + (residue * other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun times(other: Int): IntModulo = + IntModulo( + (residue * other) % modulus, + modulus, + toCheckInput = false + ) + operator fun div(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not divide two residue different modulo" } + val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other.residue, modulus) + require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" } + return IntModulo( + (residue * reciprocalCandidate) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun div(other: Int): IntModulo { + val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other, modulus) + require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" } + return IntModulo( + (residue * reciprocalCandidate) % modulus, + modulus, + toCheckInput = false + ) + } + override fun equals(other: Any?): Boolean = + when (other) { + is IntModulo -> residue == other.residue && modulus == other.modulus + else -> false + } + + override fun hashCode(): Int = residue.hashCode() + + override fun toString(): String = "$residue mod $modulus" +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") +class IntModuloRing : Ring, ScaleOperations { + + val modulus: Int + + constructor(modulus: Int) { + require(modulus != 0) { "modulus can not be zero" } + this.modulus = if (modulus < 0) -modulus else modulus + } + + override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) + override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false) + + fun number(arg: Int): IntModulo = IntModulo(arg, modulus, toCheckInput = false) + + override inline fun add(left: IntModulo, right: IntModulo): IntModulo = left + right + override inline fun multiply(left: IntModulo, right: IntModulo): IntModulo = left * right + + override inline fun IntModulo.unaryMinus(): IntModulo = -this + override inline fun IntModulo.plus(arg: IntModulo): IntModulo = this + arg + override inline fun IntModulo.minus(arg: IntModulo): IntModulo = this - arg + override inline fun IntModulo.times(arg: IntModulo): IntModulo = this * arg + inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg + + override fun scale(a: IntModulo, value: Double): IntModulo = a * value.toInt() +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt new file mode 100644 index 000000000..ffab2157c --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.PolynomialSpace + + +fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, ring.modulus) }) +fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, modulus) }) + +fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) +fun PolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt new file mode 100644 index 000000000..0a3d00e96 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps + +@Suppress("NAME_SHADOWING") +class Rational { + companion object { + val ZERO: Rational = Rational(0L) + val ONE: Rational = Rational(1L) + } + + val numerator: Long + val denominator: Long + + internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { + if (toCheckInput) { + if (denominator == 0L) throw ArithmeticException("/ by zero") + + val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < 0L) -it else it } + + this.numerator = numerator / greatestCommonDivider + this.denominator = denominator / greatestCommonDivider + } else { + this.numerator = numerator + this.denominator = denominator + } + } + + constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) + constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) + constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) + constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) + constructor(numerator: Int) : this(numerator.toLong(), 1L, false) + constructor(numerator: Long) : this(numerator, 1L, false) + + operator fun unaryPlus(): Rational = this + operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + operator fun plus(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val dividedThisDenominator = denominator / denominatorsGcd + val dividedOtherDenominator = other.denominator / denominatorsGcd + val numeratorCandidate = numerator * dividedOtherDenominator + dividedThisDenominator * other.numerator + val secondGcd = gcd(numeratorCandidate, denominatorsGcd) + return Rational( + numeratorCandidate / secondGcd, + dividedThisDenominator * (other.denominator / secondGcd), + toCheckInput = false + ) + } + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator, + toCheckInput = false + ) + operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator, + toCheckInput = false + ) + operator fun minus(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val dividedThisDenominator = denominator / denominatorsGcd + val dividedOtherDenominator = other.denominator / denominatorsGcd + val numeratorCandidate = numerator * dividedOtherDenominator - dividedThisDenominator * other.numerator + val secondGcd = gcd(numeratorCandidate, denominatorsGcd) + return Rational( + numeratorCandidate / secondGcd, + dividedThisDenominator * (other.denominator / secondGcd), + toCheckInput = false + ) + } + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator, + toCheckInput = false + ) + operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator, + toCheckInput = false + ) + operator fun times(other: Rational): Rational { + val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator) + val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator) + return Rational( + (numerator / otherDenominatorAndThisNumeratorGcd) * (other.numerator / thisDenominatorAndOtherNumeratorGcd), + (denominator / thisDenominatorAndOtherNumeratorGcd) * (other.denominator / otherDenominatorAndThisNumeratorGcd), + toCheckInput = false + ) + } + operator fun times(other: Int): Rational { + val other = other.toLong() + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + operator fun times(other: Long): Rational { + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + operator fun div(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val numeratorsGcd = gcd(numerator, other.numerator) + return Rational( + (numerator / numeratorsGcd) * (other.denominator / denominatorsGcd), + (denominator / denominatorsGcd) * (other.numerator / numeratorsGcd) + ) + } + operator fun div(other: Int): Rational { + val other = other.toLong() + val numeratorAndOtherGcd = gcd(numerator, other) + return Rational( + numerator / numeratorAndOtherGcd, + denominator * (other / numeratorAndOtherGcd), + toCheckInput = false + ) + } + operator fun div(other: Long): Rational { + val numeratorAndOtherGcd = gcd(numerator, other) + return Rational( + numerator / numeratorAndOtherGcd, + denominator * (other / numeratorAndOtherGcd), + toCheckInput = false + ) + } + override fun equals(other: Any?): Boolean = + when (other) { + is Rational -> numerator == other.numerator && denominator == other.denominator + is Int -> numerator == other && denominator == 1L + is Long -> numerator == other && denominator == 1L + else -> false + } + + override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode() + + override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator" +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") +@OptIn(UnstableKMathAPI::class) +object RationalField : Field, NumbersAddOps { + override inline val zero: Rational get() = Rational.ZERO + override inline val one: Rational get() = Rational.ONE + + override inline fun number(value: Number): Rational = Rational(value.toLong()) + + override inline fun add(left: Rational, right: Rational): Rational = left + right + override inline fun multiply(left: Rational, right: Rational): Rational = left * right + override inline fun divide(left: Rational, right: Rational): Rational = left / right + override inline fun scale(a: Rational, value: Double): Rational = a * number(value) + + override inline fun Rational.unaryMinus(): Rational = -this + override inline fun Rational.plus(arg: Rational): Rational = this + arg + override inline fun Rational.minus(arg: Rational): Rational = this - arg + override inline fun Rational.times(arg: Rational): Rational = this * arg + override inline fun Rational.div(arg: Rational): Rational = this / arg +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt new file mode 100644 index 000000000..61b50f128 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import kotlin.math.abs + + +internal data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) + +internal tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) + +internal fun bezoutIdentityWithGCD(a: Int, b: Int): BezoutIdentityWithGCD = + when { + a < 0 && b < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, -second, gcd) } + a < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, second, gcd) } + b < 0 -> with(bezoutIdentityWithGCDInternalLogic(a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(first, -second, gcd) } + else -> bezoutIdentityWithGCDInternalLogic(a, b, 1, 0, 0, 1) + } + +internal tailrec fun bezoutIdentityWithGCDInternalLogic(a: Int, b: Int, m1: Int, m2: Int, m3: Int, m4: Int): BezoutIdentityWithGCD = + if (b == 0) BezoutIdentityWithGCD(m1, m3, a) + else { + val quotient = a / b + val reminder = a % b + bezoutIdentityWithGCDInternalLogic(b, reminder, m2, m1 - quotient * m2, m4, m3 - quotient * m4) + } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 9f48a15ea..32fc08ae4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt index 9f2d71554..188f8d15f 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt index afeba0be4..4a15e96c3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt index 1143036d4..c0ca6c484 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt index 4c7d816d4..851a8ab7d 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-geometry/README.md b/kmath-geometry/README.md index 6602f5510..72d275697 100644 --- a/kmath-geometry/README.md +++ b/kmath-geometry/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-geometry:0.3.0' + implementation 'space.kscience:kmath-geometry:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-geometry:0.3.0") + implementation("space.kscience:kmath-geometry:0.3.1-dev-1") } ``` diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 7eb814683..52d76d5d2 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,15 +1,15 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") } -kotlin.sourceSets.commonMain { - dependencies { - api(project(":kmath-core")) +kscience{ + native() + withContextReceivers() + dependencies{ + api(projects.kmath.kmathComplex) } } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt new file mode 100644 index 000000000..162130908 --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2018-2022 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.geometry + +import kotlin.math.PI + +/** + * A circle in 2D space + */ +public data class Circle2D( + public val center: DoubleVector2D, + public val radius: Double +) + +public val Circle2D.circumference: Double get() = radius * 2 * PI diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index d00575bcc..a8310503c 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -1,53 +1,69 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.geometry import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke +import kotlin.math.pow import kotlin.math.sqrt -@OptIn(UnstableKMathAPI::class) -public interface Vector2D : Point, Vector { - public val x: Double - public val y: Double +public interface Vector2D : Point, Vector { + public val x: T + public val y: T override val size: Int get() = 2 - override operator fun get(index: Int): Double = when (index) { + override operator fun get(index: Int): T = when (index) { 0 -> x 1 -> y else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y).iterator() + override operator fun iterator(): Iterator = iterator { + yield(x) + yield(y) + } } -public val Vector2D.r: Double - get() = Euclidean2DSpace { norm() } -@Suppress("FunctionName") -public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) +public operator fun Vector2D.component1(): T = x +public operator fun Vector2D.component2(): T = y + +public typealias DoubleVector2D = Vector2D + +public val Vector2D.r: Double get() = Euclidean2DSpace.norm(this) -private data class Vector2DImpl( - override val x: Double, - override val y: Double, -) : Vector2D /** * 2D Euclidean space */ -public object Euclidean2DSpace : GeometrySpace, ScaleOperations { - override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) } +public object Euclidean2DSpace : GeometrySpace, + ScaleOperations, + Norm { - public fun Vector2D.norm(): Double = sqrt(x * x + y * y) - override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y) + private data class Vector2DImpl( + override val x: Double, + override val y: Double, + ) : DoubleVector2D - override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() - override fun add(left: Vector2D, right: Vector2D): Vector2D = Vector2D(left.x + right.x, left.y + right.y) - override fun scale(a: Vector2D, value: Double): Vector2D = Vector2D(a.x * value, a.y * value) - override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y + public fun vector(x: Number, y: Number): DoubleVector2D = Vector2DImpl(x.toDouble(), y.toDouble()) + + override val zero: DoubleVector2D by lazy { vector(0.0, 0.0) } + + override fun norm(arg: DoubleVector2D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2)) + + override fun DoubleVector2D.unaryMinus(): DoubleVector2D = vector(-x, -y) + + override fun DoubleVector2D.distanceTo(other: DoubleVector2D): Double = norm(this - other) + override fun add(left: DoubleVector2D, right: DoubleVector2D): DoubleVector2D = + vector(left.x + right.x, left.y + right.y) + + override fun scale(a: DoubleVector2D, value: Double): DoubleVector2D = vector(a.x * value, a.y * value) + override fun DoubleVector2D.dot(other: DoubleVector2D): Double = x * other.x + y * other.y + + public val xAxis: DoubleVector2D = vector(1.0, 0.0) + public val yAxis: DoubleVector2D = vector(0.0, 1.0) } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index e12563b46..d214e4edf 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -1,58 +1,84 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.geometry import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer +import kotlin.math.pow import kotlin.math.sqrt -@OptIn(UnstableKMathAPI::class) -public interface Vector3D : Point, Vector { - public val x: Double - public val y: Double - public val z: Double +public interface Vector3D : Point, Vector { + public val x: T + public val y: T + public val z: T override val size: Int get() = 3 - override operator fun get(index: Int): Double = when (index) { + override operator fun get(index: Int): T = when (index) { 0 -> x 1 -> y 2 -> z else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y, z).iterator() + override operator fun iterator(): Iterator = listOf(x, y, z).iterator() } -@Suppress("FunctionName") -public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) +public operator fun Vector3D.component1(): T = x +public operator fun Vector3D.component2(): T = y +public operator fun Vector3D.component3(): T = z -public val Vector3D.r: Double get() = Euclidean3DSpace { norm() } +public fun Buffer.asVector3D(): Vector3D = object : Vector3D { + init { + require(this@asVector3D.size == 3) { "Buffer of size 3 is required for Vector3D" } + } -private data class Vector3DImpl( - override val x: Double, - override val y: Double, - override val z: Double, -) : Vector3D + override val x: T get() = this@asVector3D[0] + override val y: T get() = this@asVector3D[1] + override val z: T get() = this@asVector3D[2] -public object Euclidean3DSpace : GeometrySpace, ScaleOperations { - override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } + override fun toString(): String = this@asVector3D.toString() +} - public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) - override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z) +public typealias DoubleVector3D = Vector3D - override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() +public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this) - override fun add(left: Vector3D, right: Vector3D): Vector3D = - Vector3D(left.x + right.x, left.y + right.y, left.z + right.z) +public object Euclidean3DSpace : GeometrySpace, ScaleOperations, + Norm { + private data class Vector3DImpl( + override val x: Double, + override val y: Double, + override val z: Double, + ) : DoubleVector3D - override fun scale(a: Vector3D, value: Double): Vector3D = - Vector3D(a.x * value, a.y * value, a.z * value) + public fun vector(x: Number, y: Number, z: Number): DoubleVector3D = + Vector3DImpl(x.toDouble(), y.toDouble(), z.toDouble()) - override fun Vector3D.dot(other: Vector3D): Double = + override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) } + + override fun norm(arg: DoubleVector3D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2) + arg.z.pow(2)) + + public fun DoubleVector3D.norm(): Double = norm(this) + + override fun DoubleVector3D.unaryMinus(): DoubleVector3D = vector(-x, -y, -z) + + override fun DoubleVector3D.distanceTo(other: DoubleVector3D): Double = (this - other).norm() + + override fun add(left: DoubleVector3D, right: DoubleVector3D): DoubleVector3D = + vector(left.x + right.x, left.y + right.y, left.z + right.z) + + override fun scale(a: DoubleVector3D, value: Double): DoubleVector3D = + vector(a.x * value, a.y * value, a.z * value) + + override fun DoubleVector3D.dot(other: DoubleVector3D): Double = x * other.x + y * other.y + z * other.z + + public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0) + public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0) + public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0) } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index d4245c744..854d84b65 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -1,16 +1,17 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.geometry import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations public interface Vector -public interface GeometrySpace : Group, ScaleOperations { +public interface GeometrySpace : Group, ScaleOperations, Norm { /** * L2 distance */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index 8c6ccb55e..bf14d6d4a 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt @@ -1,11 +1,20 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.geometry +/** + * A line formed by [base] vector of start and a [direction] vector. Direction vector is not necessarily normalized, + * but its length does not affect line properties + */ public data class Line(val base: V, val direction: V) -public typealias Line2D = Line -public typealias Line3D = Line +public typealias Line2D = Line +public typealias Line3D = Line + +/** + * A directed line segment between [begin] and [end] + */ +public data class LineSegment(val begin: V, val end: V) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt index a7a28b596..21045e94e 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt new file mode 100644 index 000000000..e7b0afcda --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt @@ -0,0 +1,79 @@ +/* + * 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.geometry + +import kotlin.jvm.JvmInline +import kotlin.math.PI + +public sealed interface Angle { + public fun toRadians(): Radians + public fun toDegrees(): Degrees + + public operator fun plus(other: Angle): Angle + public operator fun minus(other: Angle): Angle + + public operator fun times(other: Number): Angle + public operator fun div(other: Number): Angle + public operator fun unaryMinus(): Angle +} + +/** + * Type safe radians + */ +@JvmInline +public value class Radians(public val value: Double) : Angle { + override fun toRadians(): Radians = this + override fun toDegrees(): Degrees = Degrees(value * 180 / PI) + + public override fun plus(other: Angle): Radians = Radians(value + other.toRadians().value) + public override fun minus(other: Angle): Radians = Radians(value - other.toRadians().value) + + public override fun times(other: Number): Radians = Radians(value + other.toDouble()) + public override fun div(other: Number): Radians = Radians(value / other.toDouble()) + public override fun unaryMinus(): Radians = Radians(-value) +} + +public fun sin(angle: Angle): Double = kotlin.math.sin(angle.toRadians().value) +public fun cos(angle: Angle): Double = kotlin.math.cos(angle.toRadians().value) +public fun tan(angle: Angle): Double = kotlin.math.tan(angle.toRadians().value) + +public val Number.radians: Radians get() = Radians(toDouble()) + +/** + * Type safe degrees + */ +@JvmInline +public value class Degrees(public val value: Double) : Angle { + override fun toRadians(): Radians = Radians(value * PI / 180) + override fun toDegrees(): Degrees = this + + public override fun plus(other: Angle): Degrees = Degrees(value + other.toDegrees().value) + public override fun minus(other: Angle): Degrees = Degrees(value - other.toDegrees().value) + + public override fun times(other: Number): Degrees = Degrees(value + other.toDouble()) + public override fun div(other: Number): Degrees = Degrees(value / other.toDouble()) + public override fun unaryMinus(): Degrees = Degrees(-value) +} + +public val Number.degrees: Degrees get() = Degrees(toDouble()) + +/** + * A holder class for Pi representation in radians and degrees + */ +public object Pi { + public val radians: Radians = Radians(PI) + public val degrees: Degrees = radians.toDegrees() +} + +public object PiTimes2 { + public val radians: Radians = Radians(2 * PI) + public val degrees: Degrees = radians.toDegrees() +} + +public object PiDiv2 { + public val radians: Radians = Radians(PI / 2) + public val degrees: Degrees = radians.toDegrees() +} \ No newline at end of file diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Projections.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt similarity index 93% rename from kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Projections.kt rename to kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt index 5e299f450..6950abbdc 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Projections.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt @@ -1,10 +1,12 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.geometry +//TODO move vector to receiver + /** * Project vector onto a line. * @param vector to project diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt new file mode 100644 index 000000000..487af7e50 --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2018-2022 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.geometry + +import space.kscience.kmath.complex.Quaternion +import space.kscience.kmath.complex.QuaternionField +import space.kscience.kmath.complex.normalized +import space.kscience.kmath.complex.reciprocal +import space.kscience.kmath.linear.* +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import kotlin.math.pow +import kotlin.math.sqrt + +internal fun DoubleVector3D.toQuaternion(): Quaternion = Quaternion(0.0, x, y, z) + +/** + * Angle in radians denoted by this quaternion rotation + */ +public val Quaternion.theta: Radians get() = (kotlin.math.acos(normalized().w) * 2).radians + +/** + * Create a normalized Quaternion from rotation angle and rotation vector + */ +public fun Quaternion.Companion.fromRotation(theta: Angle, vector: DoubleVector3D): Quaternion { + val s = sin(theta / 2) + val c = cos(theta / 2) + val norm = with(Euclidean3DSpace) { vector.norm() } + return Quaternion(c, vector.x * s / norm, vector.y * s / norm, vector.z * s / norm) +} + +/** + * An axis of quaternion rotation + */ +public val Quaternion.vector: DoubleVector3D + get() { + return object : DoubleVector3D { + private val sint2 = sqrt(1 - w * w) + override val x: Double get() = this@vector.x / sint2 + override val y: Double get() = this@vector.y / sint2 + override val z: Double get() = this@vector.z / sint2 + override fun toString(): String = listOf(x, y, z).toString() + } + } + +/** + * Rotate a vector in a [Euclidean3DSpace] + */ +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, q: Quaternion): DoubleVector3D = with(QuaternionField) { + val p = vector.toQuaternion() + (q * p * q.reciprocal).vector +} + +/** + * Use a composition of quaternions to create a rotation + */ +@UnstableKMathAPI +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, composition: QuaternionField.() -> Quaternion): DoubleVector3D = + rotate(vector, QuaternionField.composition()) + +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, matrix: Matrix): DoubleVector3D { + require(matrix.colNum == 3 && matrix.rowNum == 3) { "Square 3x3 rotation matrix is required" } + return with(DoubleField.linearSpace) { matrix.dot(vector).asVector3D() } +} + +/** + * Convert a [Quaternion] to a rotation matrix + */ +@OptIn(UnstableKMathAPI::class) +public fun Quaternion.toRotationMatrix( + linearSpace: LinearSpace = DoubleField.linearSpace, +): Matrix { + val s = QuaternionField.norm(this).pow(-2) + return linearSpace.matrix(3, 3)( + 1.0 - 2 * s * (y * y + z * z), 2 * s * (x * y - z * w), 2 * s * (x * z + y * w), + 2 * s * (x * y + z * w), 1.0 - 2 * s * (x * x + z * z), 2 * s * (y * z - x * w), + 2 * s * (x * z - y * w), 2 * s * (y * z + x * w), 1.0 - 2 * s * (x * x + y * y) + ) +} + +/** + * taken from https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + */ +public fun Quaternion.Companion.fromRotationMatrix(matrix: Matrix): Quaternion { + require(matrix.colNum == 3 && matrix.rowNum == 3) { "Rotation matrix should be 3x3 but is ${matrix.rowNum}x${matrix.colNum}" } + val trace = matrix[0, 0] + matrix[1, 1] + matrix[2, 2] + + return if (trace > 0) { + val s = sqrt(trace + 1.0) * 2 // S=4*qw + Quaternion( + w = 0.25 * s, + x = (matrix[2, 1] - matrix[1, 2]) / s, + y = (matrix[0, 2] - matrix[2, 0]) / s, + z = (matrix[1, 0] - matrix[0, 1]) / s, + ) + } else if ((matrix[0, 0] > matrix[1, 1]) && (matrix[0, 0] > matrix[2, 2])) { + val s = sqrt(1.0 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2]) * 2 // S=4*qx + Quaternion( + w = (matrix[2, 1] - matrix[1, 2]) / s, + x = 0.25 * s, + y = (matrix[0, 1] + matrix[1, 0]) / s, + z = (matrix[0, 2] + matrix[2, 0]) / s, + ) + } else if (matrix[1, 1] > matrix[2, 2]) { + val s = sqrt(1.0 + matrix[1, 1] - matrix[0, 0] - matrix[2, 2]) * 2 // S=4*qy + Quaternion( + w = (matrix[0, 2] - matrix[2, 0]) / s, + x = (matrix[0, 1] + matrix[1, 0]) / s, + y = 0.25 * s, + z = (matrix[1, 2] + matrix[2, 1]) / s, + ) + } else { + val s = sqrt(1.0 + matrix[2, 2] - matrix[0, 0] - matrix[1, 1]) * 2 // S=4*qz + Quaternion( + w = (matrix[1, 0] - matrix[0, 1]) / s, + x = (matrix[0, 2] + matrix[2, 0]) / s, + y = (matrix[1, 2] + matrix[2, 1]) / s, + z = 0.25 * s, + ) + } +} + +public enum class RotationOrder { + // proper Euler + XZX, + XYX, + YXY, + YZY, + ZYZ, + ZXZ, + + //Tait–Bryan + XZY, + XYZ, + YXZ, + YZX, + ZYX, + ZXY +} + +/** + * Based on https://github.com/mrdoob/three.js/blob/master/src/math/Quaternion.js + */ +public fun Quaternion.Companion.fromEuler( + a: Angle, + b: Angle, + c: Angle, + rotationOrder: RotationOrder, +): Quaternion { + val c1 = cos (a / 2) + val c2 = cos (b / 2) + val c3 = cos (c / 2) + + val s1 = sin (a / 2) + val s2 = sin (b / 2) + val s3 = sin (c / 2) + + return when (rotationOrder) { + + RotationOrder.XYZ -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + + RotationOrder.YXZ -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.ZXY -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + + + RotationOrder.ZYX -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.YZX -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.XZY -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + else -> TODO("Proper Euler rotation orders are not supported yet") + } +} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt index 6b5f474bc..22cbee6f0 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -12,16 +12,16 @@ import kotlin.test.assertEquals internal class Euclidean2DSpaceTest { @Test fun zero() { - assertVectorEquals(Vector2D(0.0, 0.0), Euclidean2DSpace.zero) + assertVectorEquals(Euclidean2DSpace.vector(0.0, 0.0), Euclidean2DSpace.zero) } @Test fun norm() { with(Euclidean2DSpace) { - assertEquals(0.0, zero.norm()) - assertEquals(1.0, Vector2D(1.0, 0.0).norm()) - assertEquals(sqrt(2.0), Vector2D(1.0, 1.0).norm()) - assertEquals(sqrt(5.002001), Vector2D(-2.0, 1.001).norm()) + assertEquals(0.0, norm(zero)) + assertEquals(1.0, norm(vector(1.0, 0.0))) + assertEquals(sqrt(2.0), norm(vector(1.0, 1.0))) + assertEquals(sqrt(5.002001), norm(vector(-2.0, 1.001))) } } @@ -29,16 +29,16 @@ internal class Euclidean2DSpaceTest { fun dotProduct() { with(Euclidean2DSpace) { assertEquals(0.0, zero dot zero) - assertEquals(0.0, zero dot Vector2D(1.0, 0.0)) - assertEquals(0.0, Vector2D(-2.0, 0.001) dot zero) - assertEquals(0.0, Vector2D(1.0, 0.0) dot Vector2D(0.0, 1.0)) + assertEquals(0.0, zero dot vector(1.0, 0.0)) + assertEquals(0.0, vector(-2.0, 0.001) dot zero) + assertEquals(0.0, vector(1.0, 0.0) dot vector(0.0, 1.0)) - assertEquals(1.0, Vector2D(1.0, 0.0) dot Vector2D(1.0, 0.0)) - assertEquals(-2.0, Vector2D(0.0, 1.0) dot Vector2D(1.0, -2.0)) - assertEquals(2.0, Vector2D(1.0, 1.0) dot Vector2D(1.0, 1.0)) - assertEquals(4.001001, Vector2D(-2.0, 1.001) dot Vector2D(-2.0, 0.001)) + assertEquals(1.0, vector(1.0, 0.0) dot vector(1.0, 0.0)) + assertEquals(-2.0, vector(0.0, 1.0) dot vector(1.0, -2.0)) + assertEquals(2.0, vector(1.0, 1.0) dot vector(1.0, 1.0)) + assertEquals(4.001001, vector(-2.0, 1.001) dot vector(-2.0, 0.001)) - assertEquals(-4.998, Vector2D(1.0, 2.0) dot Vector2D(-5.0, 0.001)) + assertEquals(-4.998, vector(1.0, 2.0) dot vector(-5.0, 0.001)) } } @@ -46,12 +46,12 @@ internal class Euclidean2DSpaceTest { fun add() { with(Euclidean2DSpace) { assertVectorEquals( - Vector2D(-2.0, 0.001), - Vector2D(-2.0, 0.001) + zero + vector(-2.0, 0.001), + vector(-2.0, 0.001) + zero ) assertVectorEquals( - Vector2D(-3.0, 3.001), - Vector2D(2.0, 3.0) + Vector2D(-5.0, 0.001) + vector(-3.0, 3.001), + vector(2.0, 3.0) + vector(-5.0, 0.001) ) } } @@ -59,9 +59,9 @@ internal class Euclidean2DSpaceTest { @Test fun multiply() { with(Euclidean2DSpace) { - assertVectorEquals(Vector2D(-4.0, 0.0), Vector2D(-2.0, 0.0) * 2) - assertVectorEquals(Vector2D(4.0, 0.0), Vector2D(-2.0, 0.0) * -2) - assertVectorEquals(Vector2D(300.0, 0.0003), Vector2D(100.0, 0.0001) * 3) + assertVectorEquals(vector(-4.0, 0.0), vector(-2.0, 0.0) * 2) + assertVectorEquals(vector(4.0, 0.0), vector(-2.0, 0.0) * -2) + assertVectorEquals(vector(300.0, 0.0003), vector(100.0, 0.0001) * 3) } } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt index 0bc91e77e..6d9a169eb 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,21 +11,21 @@ import kotlin.test.assertEquals internal class Euclidean3DSpaceTest { @Test fun zero() { - assertVectorEquals(Vector3D(0.0, 0.0, 0.0), Euclidean3DSpace.zero) + assertVectorEquals(Euclidean3DSpace.vector(0.0, 0.0, 0.0), Euclidean3DSpace.zero) } @Test fun distance() { with(Euclidean3DSpace) { assertEquals(0.0, zero.distanceTo(zero)) - assertEquals(1.0, zero.distanceTo(Vector3D(1.0, 0.0, 0.0))) - assertEquals(kotlin.math.sqrt(5.000001), Vector3D(1.0, -2.0, 0.001).distanceTo(zero)) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(0.0, Vector3D(1.0, 0.0, 0.0).distanceTo(Vector3D(1.0, 0.0, 0.0))) - assertEquals(kotlin.math.sqrt(2.0), Vector3D(1.0, 0.0, 0.0).distanceTo(Vector3D(1.0, 1.0, 1.0))) - assertEquals(3.1622778182822584, Vector3D(0.0, 1.0, 0.0).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(9.695050335093676, Vector3D(1.0, 2.0, 3.0).distanceTo(Vector3D(7.0, -5.0, 0.001))) + assertEquals(1.0, zero.distanceTo(vector(1.0, 0.0, 0.0))) + assertEquals(kotlin.math.sqrt(5.000001), vector(1.0, -2.0, 0.001).distanceTo(zero)) + assertEquals(0.0, vector(1.0, -2.0, 0.001).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(0.0, vector(1.0, 0.0, 0.0).distanceTo(vector(1.0, 0.0, 0.0))) + assertEquals(kotlin.math.sqrt(2.0), vector(1.0, 0.0, 0.0).distanceTo(vector(1.0, 1.0, 1.0))) + assertEquals(3.1622778182822584, vector(0.0, 1.0, 0.0).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(0.0, vector(1.0, -2.0, 0.001).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(9.695050335093676, vector(1.0, 2.0, 3.0).distanceTo(vector(7.0, -5.0, 0.001))) } } @@ -33,9 +33,9 @@ internal class Euclidean3DSpaceTest { fun norm() { with(Euclidean3DSpace) { assertEquals(0.0, zero.norm()) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0).norm()) - assertEquals(kotlin.math.sqrt(3.0), Vector3D(1.0, 1.0, 1.0).norm()) - assertEquals(kotlin.math.sqrt(5.000001), Vector3D(1.0, -2.0, 0.001).norm()) + assertEquals(1.0, vector(1.0, 0.0, 0.0).norm()) + assertEquals(kotlin.math.sqrt(3.0), vector(1.0, 1.0, 1.0).norm()) + assertEquals(kotlin.math.sqrt(5.000001), vector(1.0, -2.0, 0.001).norm()) } } @@ -43,16 +43,16 @@ internal class Euclidean3DSpaceTest { fun dotProduct() { with(Euclidean3DSpace) { assertEquals(0.0, zero dot zero) - assertEquals(0.0, zero dot Vector3D(1.0, 0.0, 0.0)) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001) dot zero) + assertEquals(0.0, zero dot vector(1.0, 0.0, 0.0)) + assertEquals(0.0, vector(1.0, -2.0, 0.001) dot zero) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0) dot Vector3D(1.0, 0.0, 0.0)) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0) dot Vector3D(1.0, 1.0, 1.0)) - assertEquals(-2.0, Vector3D(0.0, 1.0, 0.0) dot Vector3D(1.0, -2.0, 0.001)) - assertEquals(3.0, Vector3D(1.0, 1.0, 1.0) dot Vector3D(1.0, 1.0, 1.0)) - assertEquals(5.000001, Vector3D(1.0, -2.0, 0.001) dot Vector3D(1.0, -2.0, 0.001)) + assertEquals(1.0, vector(1.0, 0.0, 0.0) dot vector(1.0, 0.0, 0.0)) + assertEquals(1.0, vector(1.0, 0.0, 0.0) dot vector(1.0, 1.0, 1.0)) + assertEquals(-2.0, vector(0.0, 1.0, 0.0) dot vector(1.0, -2.0, 0.001)) + assertEquals(3.0, vector(1.0, 1.0, 1.0) dot vector(1.0, 1.0, 1.0)) + assertEquals(5.000001, vector(1.0, -2.0, 0.001) dot vector(1.0, -2.0, 0.001)) - assertEquals(-2.997, Vector3D(1.0, 2.0, 3.0) dot Vector3D(7.0, -5.0, 0.001)) + assertEquals(-2.997, vector(1.0, 2.0, 3.0) dot vector(7.0, -5.0, 0.001)) } } @@ -60,12 +60,12 @@ internal class Euclidean3DSpaceTest { fun add() { with(Euclidean3DSpace) { assertVectorEquals( - Vector3D(1.0, -2.0, 0.001), - Vector3D(1.0, -2.0, 0.001) + zero + vector(1.0, -2.0, 0.001), + vector(1.0, -2.0, 0.001) + zero ) assertVectorEquals( - Vector3D(8.0, -3.0, 3.001), - Vector3D(1.0, 2.0, 3.0) + Vector3D(7.0, -5.0, 0.001) + vector(8.0, -3.0, 3.001), + vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001) ) } } @@ -73,7 +73,7 @@ internal class Euclidean3DSpaceTest { @Test fun multiply() { with(Euclidean3DSpace) { - assertVectorEquals(Vector3D(2.0, -4.0, 0.0), Vector3D(1.0, -2.0, 0.0) * 2) + assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2) } } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt index dfb65a57c..cc74b06e3 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -12,14 +12,14 @@ internal class ProjectionAlongTest { @Test fun projectionIntoYEqualsX() { with(Euclidean2DSpace) { - val normal = Vector2D(-2.0, 2.0) - val base = Vector2D(2.3, 2.3) + val normal = vector(-2.0, 2.0) + val base = vector(2.3, 2.3) assertVectorEquals(zero, projectAlong(zero, normal, base)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val d = (y - x) / 2.0 - assertVectorEquals(Vector2D(x + d, y - d), projectAlong(Vector2D(x, y), normal, base)) + assertVectorEquals(vector(x + d, y - d), projectAlong(vector(x, y), normal, base)) } } } @@ -30,28 +30,28 @@ internal class ProjectionAlongTest { val a = 5.0 val b = -3.0 val c = -15.0 - val normal = Vector2D(-5.0, 3.0) - val base = Vector2D(3.0, 0.0) + val normal = vector(-5.0, 3.0) + val base = vector(3.0, 0.0) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val xProj = (b * (b * x - a * y) - a * c) / (a * a + b * b) val yProj = (a * (-b * x + a * y) - b * c) / (a * a + b * b) - assertVectorEquals(Vector2D(xProj, yProj), projectAlong(Vector2D(x, y), normal, base)) + assertVectorEquals(vector(xProj, yProj), projectAlong(vector(x, y), normal, base)) } } } @Test - fun projectOntoPlane() { - val normal = Vector3D(1.0, 3.5, 0.07) - val base = Vector3D(2.0, -0.0037, 11.1111) + fun projectOntoPlane() = with(Euclidean3DSpace){ + val normal = vector(1.0, 3.5, 0.07) + val base = vector(2.0, -0.0037, 11.1111) with(Euclidean3DSpace) { val testDomain = (-10.0..10.0).generateList(0.43) for (x in testDomain) { for (y in testDomain) { for (z in testDomain) { - val v = Vector3D(x, y, z) + val v = vector(x, y, z) val result = projectAlong(v, normal, base) // assert that result is on plane diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt index 076025110..cdb8ea870 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -12,10 +12,10 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoOx() { with(Euclidean2DSpace) { - val ox = Line(zero, Vector2D(1.0, 0.0)) + val ox = Line(zero, vector(1.0, 0.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> - assertVectorEquals(Vector2D(x, 0.0), projectToLine(Vector2D(x, y), ox)) + assertVectorEquals(vector(x, 0.0), projectToLine(vector(x, y), ox)) } } } @@ -23,10 +23,10 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoOy() { with(Euclidean2DSpace) { - val line = Line(zero, Vector2D(0.0, 1.0)) + val line = Line(zero, vector(0.0, 1.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> - assertVectorEquals(Vector2D(0.0, y), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(0.0, y), projectToLine(vector(x, y), line)) } } } @@ -34,13 +34,13 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoYEqualsX() { with(Euclidean2DSpace) { - val line = Line(zero, Vector2D(1.0, 1.0)) + val line = Line(zero, vector(1.0, 1.0)) assertVectorEquals(zero, projectToLine(zero, line)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val d = (y - x) / 2.0 - assertVectorEquals(Vector2D(x + d, y - d), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(x + d, y - d), projectToLine(vector(x, y), line)) } } } @@ -51,38 +51,38 @@ internal class ProjectionOntoLineTest { val a = 5.0 val b = -3.0 val c = -15.0 - val line = Line(Vector2D(3.0, 0.0), Vector2D(3.0, 5.0)) + val line = Line(vector(3.0, 0.0), vector(3.0, 5.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val xProj = (b * (b * x - a * y) - a * c) / (a * a + b * b) val yProj = (a * (-b * x + a * y) - b * c) / (a * a + b * b) - assertVectorEquals(Vector2D(xProj, yProj), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(xProj, yProj), projectToLine(vector(x, y), line)) } } } @Test - fun projectionOntoLine3d() { + fun projectionOntoLine3d() = with(Euclidean3DSpace) { val line = Line3D( - base = Vector3D(1.0, 3.5, 0.07), - direction = Vector3D(2.0, -0.0037, 11.1111) + base = vector(1.0, 3.5, 0.07), + direction = vector(2.0, -0.0037, 11.1111) ) - with(Euclidean3DSpace) { - val testDomain = (-10.0..10.0).generateList(0.43) - for (x in testDomain) { - for (y in testDomain) { - for (z in testDomain) { - val v = Vector3D(x, y, z) - val result = projectToLine(v, line) - // assert that result is on line - assertTrue(isCollinear(result - line.base, line.direction)) - // assert that PV vector is orthogonal to direction vector - assertTrue(isOrthogonal(v - result, line.direction)) - } + val testDomain = (-10.0..10.0).generateList(0.43) + for (x in testDomain) { + for (y in testDomain) { + for (z in testDomain) { + val v = vector(x, y, z) + val result = projectToLine(v, line) + + // assert that result is on the line + assertTrue(isCollinear(result - line.base, line.direction)) + // assert that PV vector is orthogonal to direction vector + assertTrue(isOrthogonal(v - result, line.direction)) } } } + } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt new file mode 100644 index 000000000..6177382a2 --- /dev/null +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2018-2022 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.geometry + +import space.kscience.kmath.complex.Quaternion +import space.kscience.kmath.complex.normalized +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.testutils.assertBufferEquals +import kotlin.test.Test + +class RotationTest { + + @Test + fun differentRotations() = with(Euclidean3DSpace) { + val vector = vector(1.0, 1.0, 1.0) + val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() + val rotatedByQ = rotate(vector, q) + val matrix = q.toRotationMatrix() + val rotatedByM = rotate(vector, matrix) + + assertBufferEquals(rotatedByQ, rotatedByM, 1e-4) + } + + @Test + fun matrixConversion() { + + val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() + + val matrix = q.toRotationMatrix() + + assertBufferEquals(q, Quaternion.fromRotationMatrix(matrix)) + } + + @Test + fun fromRotation() { + val q = Quaternion.fromRotation(0.3.radians, Euclidean3DSpace.vector(1.0, 1.0, 1.0)) + + assertBufferEquals(DoubleBuffer(0.9887711, 0.0862781, 0.0862781, 0.0862781), q) + } + + @Test + fun fromEuler() { + val q = Quaternion.fromEuler(0.1.radians, 0.2.radians, 0.3.radians, RotationOrder.ZXY) + + assertBufferEquals(DoubleBuffer(0.9818562, 0.0342708, 0.1060205, 0.1534393), q) + } +} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt index 5e45b4870..c33567f11 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,7 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class Vector2DTest { - private val vector = Vector2D(1.0, -7.999) + private val vector = Euclidean2DSpace.vector(1.0, -7.999) @Test fun size() { diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt index 55bab4775..1c8607838 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,7 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class Vector3DTest { - private val vector = Vector3D(1.0, -7.999, 0.001) + private val vector = Euclidean3DSpace.vector(1.0, -7.999, 0.001) @Test fun size() { diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt index 0f957529d..89db22d45 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -25,12 +25,12 @@ fun grid( return xs.flatMap { x -> ys.map { y -> x to y } } } -fun assertVectorEquals(expected: Vector2D, actual: Vector2D, absoluteTolerance: Double = 1e-6) { +fun assertVectorEquals(expected: DoubleVector2D, actual: DoubleVector2D, absoluteTolerance: Double = 1e-6) { assertEquals(expected.x, actual.x, absoluteTolerance) assertEquals(expected.y, actual.y, absoluteTolerance) } -fun assertVectorEquals(expected: Vector3D, actual: Vector3D, absoluteTolerance: Double = 1e-6) { +fun assertVectorEquals(expected: DoubleVector3D, actual: DoubleVector3D, absoluteTolerance: Double = 1e-6) { assertEquals(expected.x, actual.x, absoluteTolerance) assertEquals(expected.y, actual.y, absoluteTolerance) assertEquals(expected.z, actual.z, absoluteTolerance) diff --git a/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt new file mode 100644 index 000000000..5fcd2b23e --- /dev/null +++ b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import space.kscience.kmath.geometry.GeometrySpace +import space.kscience.kmath.geometry.Line +import space.kscience.kmath.geometry.LineSegment +import space.kscience.kmath.geometry.Vector +import space.kscience.kmath.operations.Group + +/** + * Get a line, containing this [LineSegment] + */ +context(Group) public val LineSegment.line: Line get() = Line(begin, end - begin) + +/** + * Get a length of a line segment + */ +context(GeometrySpace) public val LineSegment.length: Double get() = norm(end - begin) \ No newline at end of file diff --git a/kmath-histograms/README.md b/kmath-histograms/README.md index 27f1b43ec..5fd91ee0c 100644 --- a/kmath-histograms/README.md +++ b/kmath-histograms/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-histograms:0.3.0' + implementation 'space.kscience:kmath-histograms:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-histograms:0.3.0") + implementation("space.kscience:kmath-histograms:0.3.1-dev-1") } ``` diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 51271bb0a..d31526a74 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,17 +1,18 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") } -kscience { - useAtomic() +kscience{ + native() } +//apply(plugin = "kotlinx-atomicfu") + kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-core")) + api(npmlibs.atomicfu) } } commonTest { @@ -24,5 +25,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index fe3278026..43ed24c70 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index 12edafd81..a4ae6d935 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt index 710e4478b..f9ca6a486 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt index 68b24db5d..2cefb33a5 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt index e13928394..3c687d2df 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt index 90ec29ce3..36e994bcf 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -21,14 +21,14 @@ public typealias HyperSquareBin = DomainBin /** * Multivariate histogram space for hyper-square real-field bins. - * @param bufferFactory is an optional parameter used to optimize buffer production. + * @param valueBufferFactory is an optional parameter used to optimize buffer production. */ public class UniformHistogramGroupND>( override val valueAlgebraND: FieldOpsND, private val lower: Buffer, private val upper: Buffer, private val binNums: IntArray = IntArray(lower.size) { 20 }, - private val bufferFactory: BufferFactory = Buffer.Companion::boxing, + private val valueBufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ) : HistogramGroupND { init { @@ -94,7 +94,7 @@ public class UniformHistogramGroupND>( } } hBuilder.apply(builder) - val values: BufferND = ndCounter.mapToBuffer(bufferFactory) { it.value } + val values: BufferND = ndCounter.mapToBuffer(valueBufferFactory) { it.value } return HistogramND(this, values) } @@ -114,12 +114,12 @@ public class UniformHistogramGroupND>( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: ClosedFloatingPointRange, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ranges.map(ClosedFloatingPointRange::start).asBuffer(), ranges.map(ClosedFloatingPointRange::endInclusive).asBuffer(), - bufferFactory = bufferFactory + valueBufferFactory = bufferFactory ) public fun Histogram.Companion.uniformDoubleNDFromRanges( @@ -140,7 +140,7 @@ public fun Histogram.Companion.uniformDoubleNDFromRanges( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: Pair, Int>, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ListBuffer( @@ -154,7 +154,7 @@ public fun > Histogram.Companion.uniformNDFromRanges( .map(ClosedFloatingPointRange::endInclusive) ), ranges.map(Pair, Int>::second).toIntArray(), - bufferFactory = bufferFactory + valueBufferFactory = bufferFactory ) public fun Histogram.Companion.uniformDoubleNDFromRanges( diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index ca7c2f324..717f9d7a1 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt index 09bf3939d..fd107f5e8 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt index 6bec01f9b..a7d34ff71 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt index c4eeb53cc..77dc189ee 100644 --- a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt +++ b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt @@ -1,17 +1,19 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.histogram import org.junit.jupiter.api.Test +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.real.step import kotlin.random.Random import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(UnstableKMathAPI::class) class TreeHistogramTest { @Test diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index fe6afb835..c008c76ca 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0' + implementation 'space.kscience:kmath-jafama:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0") + implementation("space.kscience:kmath-jafama:0.3.1-dev-1") } ``` diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts index 925a2bc60..da77f469d 100644 --- a/kmath-jafama/build.gradle.kts +++ b/kmath-jafama/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") } description = "Jafama integration module" @@ -14,7 +14,7 @@ repositories { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature("jafama-double", "src/main/kotlin/space/kscience/kmath/jafama/") { diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index 91d952a76..f9b8287b4 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-jupyter/README.md b/kmath-jupyter/README.md index db58ad840..3c9832625 100644 --- a/kmath-jupyter/README.md +++ b/kmath-jupyter/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jupyter:0.3.0' + implementation 'space.kscience:kmath-jupyter:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jupyter:0.3.0") + implementation("space.kscience:kmath-jupyter:0.3.1-dev-1") } ``` diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index ca1a5485f..d92b6ca0d 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") kotlin("jupyter.api") } @@ -14,7 +14,7 @@ kscience { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } kotlin.sourceSets.all { diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index 504ad693e..85797134f 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 52e8b3116..457652aaf 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0' + implementation 'space.kscience:kmath-kotlingrad:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0") + implementation("space.kscience:kmath-kotlingrad:0.3.1-dev-1") } ``` diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 2f6d41bbb..cf4a4bc1d 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } kotlin.sourceSets @@ -18,7 +17,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt index f7858e172..cd35e0c42 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt index 31b8a9286..110572140 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt index 37ce40cab..dd75a704c 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 570d7dd7f..042777c8a 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-memory/README.md b/kmath-memory/README.md index 9f4520bd8..536d7f145 100644 --- a/kmath-memory/README.md +++ b/kmath-memory/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-memory:0.3.0' + implementation 'space.kscience:kmath-memory:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-memory:0.3.0") + implementation("space.kscience:kmath-memory:0.3.1-dev-1") } ``` diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 4478e5b80..50eb448a7 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,11 +1,13 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience { + native() } readme { - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT description = """ An API and basic implementation for arranging objects in a continuous memory block. """.trimIndent() diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt index e8e51e9e2..006d57c5f 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt index 1ee1cf4e2..19bc3bae4 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt index 6153743fc..40ba84c10 100644 --- a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index aef68fd80..84f7ea412 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt index 5146d9689..b224383e4 100644 --- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt +++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-multik/README.md b/kmath-multik/README.md index edfce6f79..0f5b65b4c 100644 --- a/kmath-multik/README.md +++ b/kmath-multik/README.md @@ -6,7 +6,7 @@ JetBrains Multik connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-multik:0.3.0' + implementation 'space.kscience:kmath-multik:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-multik:0.3.0") + implementation("space.kscience:kmath-multik:0.3.1-dev-1") } ``` diff --git a/kmath-multik/build.gradle.kts b/kmath-multik/build.gradle.kts index df2292f2e..39c03ab9b 100644 --- a/kmath-multik/build.gradle.kts +++ b/kmath-multik/build.gradle.kts @@ -1,14 +1,27 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.mpp") } description = "JetBrains Multik connector" -dependencies { - api(project(":kmath-tensors")) - api("org.jetbrains.kotlinx:multik-default:0.1.0") +val multikVersion: String by rootProject.extra + +kotlin{ + sourceSets{ + commonMain{ + dependencies{ + api(project(":kmath-tensors")) + api("org.jetbrains.kotlinx:multik-core:$multikVersion") + } + } + commonTest{ + dependencies{ + api("org.jetbrains.kotlinx:multik-default:$multikVersion") + } + } + } } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt similarity index 72% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index 1dc318517..989ebcd5d 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -1,17 +1,23 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.multik +import org.jetbrains.kotlinx.multik.api.Engine +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExponentialOperations import space.kscience.kmath.operations.TrigonometricOperations -public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra(), +public class MultikDoubleAlgebra( + multikEngine: Engine +) : MultikDivisionTensorAlgebra(multikEngine), TrigonometricOperations>, ExponentialOperations> { override val elementAlgebra: DoubleField get() = DoubleField override val type: DataType get() = DataType.DoubleDataType @@ -22,10 +28,13 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra): MultikTensor = sin(arg) / cos(arg) + @PerformancePitfall override fun asin(arg: StructureND): MultikTensor = arg.map { asin(it) } + @PerformancePitfall override fun acos(arg: StructureND): MultikTensor = arg.map { acos(it) } + @PerformancePitfall override fun atan(arg: StructureND): MultikTensor = arg.map { atan(it) } override fun exp(arg: StructureND): MultikTensor = multikMath.mathEx.exp(arg.asMultik().array).wrap() @@ -42,13 +51,18 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra): MultikTensor = arg.map { asinh(it) } + @PerformancePitfall override fun acosh(arg: StructureND): MultikTensor = arg.map { acosh(it) } + @PerformancePitfall override fun atanh(arg: StructureND): MultikTensor = arg.map { atanh(it) } + + override fun scalar(value: Double): MultikTensor = Multik.ndarrayOf(value).wrap() } -public val Double.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra -public val DoubleField.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra +//public val Double.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra +//public val DoubleField.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt new file mode 100644 index 000000000..ee194ae24 --- /dev/null +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2018-2022 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.multik + +import org.jetbrains.kotlinx.multik.api.Engine +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.FloatField + +public class MultikFloatAlgebra( + multikEngine: Engine +) : MultikDivisionTensorAlgebra(multikEngine) { + override val elementAlgebra: FloatField get() = FloatField + override val type: DataType get() = DataType.FloatDataType + + override fun scalar(value: Float): MultikTensor = Multik.ndarrayOf(value).wrap() +} + + +//public val Float.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra +//public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra \ No newline at end of file diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt new file mode 100644 index 000000000..05b240787 --- /dev/null +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2018-2022 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.multik + +import org.jetbrains.kotlinx.multik.api.Engine +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.IntRing + +public class MultikIntAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { + override val elementAlgebra: IntRing get() = IntRing + override val type: DataType get() = DataType.IntDataType + override fun scalar(value: Int): MultikTensor = Multik.ndarrayOf(value).wrap() +} + +//public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra +//public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra \ No newline at end of file diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt new file mode 100644 index 000000000..e713e556e --- /dev/null +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2018-2022 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.multik + +import org.jetbrains.kotlinx.multik.api.Engine +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.LongRing + +public class MultikLongAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { + override val elementAlgebra: LongRing get() = LongRing + override val type: DataType get() = DataType.LongDataType + + override fun scalar(value: Long): MultikTensor = Multik.ndarrayOf(value).wrap() +} + + +//public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra +//public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt new file mode 100644 index 000000000..6e5ca5882 --- /dev/null +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2018-2022 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.multik + +import org.jetbrains.kotlinx.multik.api.Engine +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.ShortRing + +public class MultikShortAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { + override val elementAlgebra: ShortRing get() = ShortRing + override val type: DataType get() = DataType.ShortDataType + override fun scalar(value: Short): MultikTensor = Multik.ndarrayOf(value).wrap() +} + +//public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra +//public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra \ No newline at end of file diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt new file mode 100644 index 000000000..38d61e982 --- /dev/null +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2018-2022 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.multik + +import org.jetbrains.kotlinx.multik.ndarray.data.* +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.tensors.api.Tensor +import kotlin.jvm.JvmInline + +@JvmInline +public value class MultikTensor(public val array: MutableMultiArray) : Tensor { + override val shape: Shape get() = array.shape + + override fun get(index: IntArray): T = array[index] + + @PerformancePitfall + override fun elements(): Sequence> = + array.multiIndices.iterator().asSequence().map { it to get(it) } + + override fun set(index: IntArray, value: T) { + array[index] = value + } +} + + +internal fun MultiArray.asD1Array(): D1Array { + if (this is NDArray) + return this.asD1Array() + else throw ClassCastException("Cannot cast MultiArray to NDArray.") +} + + +internal fun MultiArray.asD2Array(): D2Array { + if (this is NDArray) + return this.asD2Array() + else throw ClassCastException("Cannot cast MultiArray to NDArray.") +} \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt similarity index 66% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 250ef7e7f..194c5fcee 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,55 +10,25 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.api.* import org.jetbrains.kotlinx.multik.api.linalg.LinAlg import org.jetbrains.kotlinx.multik.api.math.Math +import org.jetbrains.kotlinx.multik.api.stat.Statistics import org.jetbrains.kotlinx.multik.ndarray.data.* import org.jetbrains.kotlinx.multik.ndarray.operations.* import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.Shape -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.mapInPlace +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra -@JvmInline -public value class MultikTensor(public val array: MutableMultiArray) : Tensor { - override val shape: Shape get() = array.shape - - override fun get(index: IntArray): T = array[index] - - @PerformancePitfall - override fun elements(): Sequence> = - array.multiIndices.iterator().asSequence().map { it to get(it) } - - override fun set(index: IntArray, value: T) { - array[index] = value - } -} - -private fun MultiArray.asD1Array(): D1Array { - if (this is NDArray) - return this.asD1Array() - else throw ClassCastException("Cannot cast MultiArray to NDArray.") -} - - -private fun MultiArray.asD2Array(): D2Array { - if (this is NDArray) - return this.asD2Array() - else throw ClassCastException("Cannot cast MultiArray to NDArray.") -} - -public abstract class MultikTensorAlgebra> : TensorAlgebra - where T : Number, T : Comparable { +public abstract class MultikTensorAlgebra>( + private val multikEngine: Engine, +) : TensorAlgebra where T : Number, T : Comparable { public abstract val type: DataType - protected val multikMath: Math = mk.math - protected val multikLinAl: LinAlg = mk.linalg - protected val multikStat: Statistics = mk.stat - + protected val multikMath: Math = multikEngine.getMath() + protected val multikLinAl: LinAlg = multikEngine.getLinAlg() + protected val multikStat: Statistics = multikEngine.getStatistics() override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { val strides = DefaultStrides(shape) @@ -102,6 +72,20 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra } } + /** + * Transform a structure element-by element in place. + */ + public inline fun MutableStructureND.mapIndexedInPlace(operation: (index: IntArray, t: T) -> T): Unit { + if (this is MultikTensor) { + array.multiIndices.iterator().forEach { + set(it, operation(it, get(it))) + } + } else { + indices.forEach { set(it, operation(it, get(it))) } + } + } + + @OptIn(PerformancePitfall::class) override fun zip(left: StructureND, right: StructureND, transform: A.(T, T) -> T): MultikTensor { require(left.shape.contentEquals(right.shape)) { "ND array shape mismatch" } //TODO replace by ShapeMismatchException @@ -151,7 +135,7 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.plusAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.add(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.add(t, value) } } } @@ -159,7 +143,7 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.plusAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.add(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.add(t, arg[index]) } } } @@ -175,7 +159,7 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.minusAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.run { t - value } } + mapIndexedInPlace { _, t -> elementAlgebra.run { t - value } } } } @@ -183,7 +167,7 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.minusAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.run { t - arg[index] } } + mapIndexedInPlace { index, t -> elementAlgebra.run { t - arg[index] } } } } @@ -200,7 +184,7 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.timesAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.multiply(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.multiply(t, value) } } } @@ -208,16 +192,16 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra if (this is MultikTensor) { array.timesAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.multiply(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.multiply(t, arg[index]) } } } override fun StructureND.unaryMinus(): MultikTensor = asMultik().array.unaryMinus().wrap() - override fun Tensor.get(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() + override fun Tensor.getTensor(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() - override fun Tensor.transpose(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() + override fun Tensor.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() override fun Tensor.view(shape: IntArray): MultikTensor { require(shape.all { it > 0 }) @@ -240,11 +224,15 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra override fun Tensor.viewAs(other: StructureND): MultikTensor = view(other.shape) + public abstract fun scalar(value: T): MultikTensor + override fun StructureND.dot(other: StructureND): MultikTensor = if (this.shape.size == 1 && other.shape.size == 1) { - Multik.ndarrayOf( - multikLinAl.linAlgEx.dotVV(asMultik().array.asD1Array(), other.asMultik().array.asD1Array()) - ).wrap() + scalar( + multikLinAl.linAlgEx.dotVV( + asMultik().array.asD1Array(), other.asMultik().array.asD1Array() + ) + ) } else if (this.shape.size == 2 && other.shape.size == 2) { multikLinAl.linAlgEx.dotMM(asMultik().array.asD2Array(), other.asMultik().array.asD2Array()).wrap() } else if (this.shape.size == 2 && other.shape.size == 1) { @@ -254,41 +242,53 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra } override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): MultikTensor { + TODO("Diagonal embedding not implemented") } - override fun StructureND.sum(): T = asMultik().array.reduceMultiIndexed { _: IntArray, acc: T, t: T -> - elementAlgebra.add(acc, t) - } + override fun StructureND.sum(): T = multikMath.sum(asMultik().array) override fun StructureND.sum(dim: Int, keepDim: Boolean): MultikTensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.sumDN(asMultik().array, dim).wrap() } override fun StructureND.min(): T? = asMultik().array.min() override fun StructureND.min(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.minDN(asMultik().array, dim).wrap() + } + + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor { + if (keepDim) TODO("keepDim not implemented") + val res = multikMath.argMinDN(asMultik().array, dim) + return with(MultikIntAlgebra(multikEngine)) { res.wrap() } } override fun StructureND.max(): T? = asMultik().array.max() override fun StructureND.max(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.maxDN(asMultik().array, dim).wrap() } override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + val res = multikMath.argMaxDN(asMultik().array, dim) + return with(MultikIntAlgebra(multikEngine)) { res.wrap() } } } -public abstract class MultikDivisionTensorAlgebra> - : MultikTensorAlgebra(), TensorPartialDivisionAlgebra where T : Number, T : Comparable { +public abstract class MultikDivisionTensorAlgebra>( + multikEngine: Engine, +) : MultikTensorAlgebra(multikEngine), TensorPartialDivisionAlgebra where T : Number, T : Comparable { - override fun T.div(arg: StructureND): MultikTensor = arg.map { elementAlgebra.divide(this@div, it) } + override fun T.div(arg: StructureND): MultikTensor = + Multik.ones(arg.shape, type).apply { divAssign(arg.asMultik().array) }.wrap() override fun StructureND.div(arg: T): MultikTensor = - asMultik().array.deepCopy().apply { divAssign(arg) }.wrap() + asMultik().array.div(arg).wrap() override fun StructureND.div(arg: StructureND): MultikTensor = asMultik().array.div(arg.asMultik().array).wrap() @@ -297,7 +297,7 @@ public abstract class MultikDivisionTensorAlgebra> if (this is MultikTensor) { array.divAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.divide(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.divide(t, value) } } } @@ -305,39 +305,7 @@ public abstract class MultikDivisionTensorAlgebra> if (this is MultikTensor) { array.divAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.divide(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.divide(t, arg[index]) } } } -} - -public object MultikFloatAlgebra : MultikDivisionTensorAlgebra() { - override val elementAlgebra: FloatField get() = FloatField - override val type: DataType get() = DataType.FloatDataType -} - -public val Float.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra -public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra - -public object MultikShortAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: ShortRing get() = ShortRing - override val type: DataType get() = DataType.ShortDataType -} - -public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra -public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra - -public object MultikIntAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: IntRing get() = IntRing - override val type: DataType get() = DataType.IntDataType -} - -public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra -public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra - -public object MultikLongAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: LongRing get() = LongRing - override val type: DataType get() = DataType.LongDataType -} - -public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra -public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt similarity index 64% rename from kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt rename to kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index 72c43d8e6..392532d8e 100644 --- a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -1,37 +1,41 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.multik -import org.junit.jupiter.api.Test +import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra +import kotlin.test.Test import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) internal class MultikNDTest { + val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) + @Test - fun basicAlgebra(): Unit = DoubleField.multikAlgebra{ - one(2,2) + 1.0 + fun basicAlgebra(): Unit = with(multikAlgebra) { + one(2, 2) + 1.0 } @Test - fun dotResult(){ + fun dotResult() { val dim = 100 val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224) val tensor2 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12225) - val multikResult = with(DoubleField.multikAlgebra){ + val multikResult = with(multikAlgebra) { tensor1 dot tensor2 } - val defaultResult = with(DoubleField.tensorAlgebra){ + val defaultResult = with(DoubleField.tensorAlgebra) { tensor1 dot tensor2 } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 0bcae138e..bb065a300 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0' + implementation 'space.kscience:kmath-nd4j:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0") + implementation("space.kscience:kmath-nd4j:0.3.1-dev-1") } ``` diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 09264501f..e5c4af891 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } description = "ND4J NDStructure implementation and according NDAlgebra classes" @@ -13,7 +12,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature(id = "nd4jarraystructure") { "NDStructure wrapper for INDArray" } feature(id = "nd4jarrayrings") { "Rings over Nd4jArrayStructure of Int and Long" } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index e29a3f467..859773211 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -45,6 +45,7 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.mapIndexed( transform: C.(index: IntArray, T) -> T, ): Nd4jArrayStructure { @@ -53,6 +54,7 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND, right: StructureND, diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt index d4cad8996..fedad26e0 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 2a0fdc86c..0a7d15e20 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index ceb384f0d..c1772683f 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -40,12 +40,15 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): Nd4jArrayStructure + @OptIn(PerformancePitfall::class) override fun StructureND.map(transform: A.(T) -> T): Nd4jArrayStructure = structureND(shape) { index -> elementAlgebra.transform(get(index)) } + @OptIn(PerformancePitfall::class) override fun StructureND.mapIndexed(transform: A.(index: IntArray, T) -> T): Nd4jArrayStructure = structureND(shape) { index -> elementAlgebra.transform(index, get(index)) } + @OptIn(PerformancePitfall::class) override fun zip(left: StructureND, right: StructureND, transform: A.(T, T) -> T): Nd4jArrayStructure { require(left.shape.contentEquals(right.shape)) return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) } @@ -92,8 +95,8 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe } override fun StructureND.unaryMinus(): Nd4jArrayStructure = ndArray.neg().wrap() - override fun Tensor.get(i: Int): Nd4jArrayStructure = ndArray.slice(i.toLong()).wrap() - override fun Tensor.transpose(i: Int, j: Int): Nd4jArrayStructure = ndArray.swapAxes(i, j).wrap() + override fun Tensor.getTensor(i: Int): Nd4jArrayStructure = ndArray.slice(i.toLong()).wrap() + override fun Tensor.transposed(i: Int, j: Int): Nd4jArrayStructure = ndArray.swapAxes(i, j).wrap() override fun StructureND.dot(other: StructureND): Nd4jArrayStructure = ndArray.mmul(other.ndArray).wrap() override fun StructureND.min(dim: Int, keepDim: Boolean): Nd4jArrayStructure = @@ -108,6 +111,9 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun Tensor.view(shape: IntArray): Nd4jArrayStructure = ndArray.reshape(shape).wrap() override fun Tensor.viewAs(other: StructureND): Nd4jArrayStructure = view(other.shape) + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = + ndBase.get().argmin(ndArray, keepDim, dim).asIntStructure() + override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor = ndBase.get().argmax(ndArray, keepDim, dim).asIntStructure() @@ -135,6 +141,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun StructureND.atan(): Nd4jArrayStructure = Transforms.atan(ndArray).wrap() override fun StructureND.tanh(): Nd4jArrayStructure = Transforms.tanh(ndArray).wrap() override fun StructureND.atanh(): Nd4jArrayStructure = Transforms.atanh(ndArray).wrap() + override fun power(arg: StructureND, pow: Number): StructureND = Transforms.pow(arg.ndArray, pow).wrap() override fun StructureND.ceil(): Nd4jArrayStructure = Transforms.ceil(ndArray).wrap() override fun StructureND.floor(): Nd4jArrayStructure = Transforms.floor(ndArray).wrap() override fun StructureND.std(dim: Int, keepDim: Boolean): Nd4jArrayStructure = diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt index 3ca756600..401c57a7b 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 9d30c2027..9f1022fd9 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 30d01338f..d1ad746fe 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/README.md b/kmath-optimization/README.md index 63e0f43e3..d7441ebd1 100644 --- a/kmath-optimization/README.md +++ b/kmath-optimization/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-optimization:0.3.0' + implementation 'space.kscience:kmath-optimization:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-optimization:0.3.0") + implementation("space.kscience:kmath-optimization:0.3.1-dev-1") } ``` diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index b920b9267..f4256b9aa 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -1,10 +1,9 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") } -kscience { - useAtomic() +kscience{ + native() } kotlin.sourceSets { @@ -15,10 +14,11 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) + api(npmlibs.atomicfu) } } } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index 02602b068..07146625c 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt index 416d0195d..d1ceccf1a 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt index b42be4035..db154be42 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt index 78385a99b..41dcbf770 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt index babbaf6cd..669860934 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt index 07fea3126..d2182e91f 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @file:OptIn(UnstableKMathAPI::class) diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt index b4cb2f1cf..e0eeb339c 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-polynomial/README.md b/kmath-polynomial/README.md new file mode 100644 index 000000000..a5078a7e0 --- /dev/null +++ b/kmath-polynomial/README.md @@ -0,0 +1,50 @@ +# Module kmath-polynomial + +Polynomials, rational functions, and utilities + +## Features + + - [polynomial abstraction](src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Abstraction for polynomial spaces. + - [rational function abstraction](src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt) : Abstraction for rational functions spaces. + - ["list" polynomials](src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt) : List implementation of univariate polynomials. + - ["list" rational functions](src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt) : List implementation of univariate rational functions. + - ["list" polynomials and rational functions constructors](src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt) : Constructors for list polynomials and rational functions. + - ["list" polynomials and rational functions utilities](src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt) : Utilities for list polynomials and rational functions. + - ["numbered" polynomials](src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt) : Numbered implementation of multivariate polynomials. + - ["numbered" rational functions](src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt) : Numbered implementation of multivariate rational functions. + - ["numbered" polynomials and rational functions constructors](src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt) : Constructors for numbered polynomials and rational functions. + - ["numbered" polynomials and rational functions utilities](src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt) : Utilities for numbered polynomials and rational functions. + - ["labeled" polynomials](src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt) : Labeled implementation of multivariate polynomials. + - ["labeled" rational functions](src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt) : Labeled implementation of multivariate rational functions. + - ["labeled" polynomials and rational functions constructors](src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt) : Constructors for labeled polynomials and rational functions. + - ["labeled" polynomials and rational functions utilities](src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt) : Utilities for labeled polynomials and rational functions. + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-polynomial:0.3.1-dev-1`. + +**Gradle Groovy:** +```groovy +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-polynomial:0.3.1-dev-1' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:kmath-polynomial:0.3.1-dev-1") +} +``` diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts new file mode 100644 index 000000000..4e469f0d1 --- /dev/null +++ b/kmath-polynomial/build.gradle.kts @@ -0,0 +1,69 @@ +plugins { + id("space.kscience.gradle.mpp") +} + +kscience{ + native() +} + +description = "Polynomials, rational functions, and utilities" + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmathCore) + } + } +} + +dependencies { + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${npmlibs.versions.dokka.get()}") +} + +readme { + maturity = space.kscience.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature("polynomial abstraction", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt") { + "Abstraction for polynomial spaces." + } + feature("rational function abstraction", "src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt") { + "Abstraction for rational functions spaces." + } + feature("\"list\" polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt") { + "List implementation of univariate polynomials." + } + feature("\"list\" rational functions", "src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt") { + "List implementation of univariate rational functions." + } + feature("\"list\" polynomials and rational functions constructors", "src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt") { + "Constructors for list polynomials and rational functions." + } + feature("\"list\" polynomials and rational functions utilities", "src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt") { + "Utilities for list polynomials and rational functions." + } + feature("\"numbered\" polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt") { + "Numbered implementation of multivariate polynomials." + } + feature("\"numbered\" rational functions", "src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt") { + "Numbered implementation of multivariate rational functions." + } + feature("\"numbered\" polynomials and rational functions constructors", "src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt") { + "Constructors for numbered polynomials and rational functions." + } + feature("\"numbered\" polynomials and rational functions utilities", "src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt") { + "Utilities for numbered polynomials and rational functions." + } + feature("\"labeled\" polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt") { + "Labeled implementation of multivariate polynomials." + } + feature("\"labeled\" rational functions", "src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt") { + "Labeled implementation of multivariate rational functions." + } + feature("\"labeled\" polynomials and rational functions constructors", "src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt") { + "Constructors for labeled polynomials and rational functions." + } + feature("\"labeled\" polynomials and rational functions utilities", "src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt") { + "Utilities for labeled polynomials and rational functions." + } +} diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt new file mode 100644 index 000000000..662e8ca74 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -0,0 +1,529 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.operations.Ring +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents multivariate polynomial that stores its coefficients in a [Map] and terms' signatures in a [Map] that + * associates variables (of type [Symbol]) with their degree. + * + * @param C the type of constants. + */ +public data class LabeledPolynomial +@PublishedApi +internal constructor( + /** + * Map that contains coefficients of the polynomial. + * + * Every monomial \(a x_1^{d_1} ... x_n^{d_n}\) is stored as a pair "key-value" in the map, where the value is the + * coefficient \(a\) and the key is a map that associates variables in the monomial with their degree in the monomial. + * For example, coefficients of a polynomial \(5 a^2 c^3 - 6 b\) can be represented as + * ``` + * mapOf( + * mapOf( + * a to 2, + * c to 3 + * ) to 5, + * mapOf( + * b to 1 + * ) to (-6) + * ) + * ``` + * and also as + * ``` + * mapOf( + * mapOf( + * a to 2, + * c to 3 + * ) to 5, + * mapOf( + * b to 1 + * ) to (-6), + * mapOf( + * b to 1, + * c to 1 + * ) to 0 + * ) + * ``` + * where \(a\), \(b\) and \(c\) are corresponding [Symbol] objects. + * + * It is not prohibited to put extra zero monomials into the map (as for \(0 b c\) in the example). But the + * bigger the coefficients map the worse performance of arithmetical operations performed on it. Thus, it is + * recommended not to put (or even to remove) extra (or useless) monomials in the coefficients map. + * @usesMathJax + */ + public val coefficients: Map, C> +) { + override fun toString(): String = "LabeledPolynomial$coefficients" +} + +/** + * Arithmetic context for multivariate polynomials with coefficients stored as a [Map] and terms' signatures stored as a + * [Map] constructed with the provided [ring] of constants. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class LabeledPolynomialSpace>( + public override val ring: A, +) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + public override operator fun Symbol.plus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomialAsIs( + mapOf(this@plus to 1U) to constantOne, + ) + else LabeledPolynomialAsIs( + mapOf(this@plus to 1U) to constantOne, + emptyMap() to other.asConstant(), + ) + /** + * Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + public override operator fun Symbol.minus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomialAsIs( + mapOf(this@minus to 1U) to constantOne, + ) + else LabeledPolynomialAsIs( + mapOf(this@minus to 1U) to constantOne, + emptyMap() to (-other).asConstant(), + ) + /** + * Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + public override operator fun Symbol.times(other: Int): LabeledPolynomial = + if (other == 0) zero + else LabeledPolynomialAsIs( + mapOf(this to 1U) to other.asConstant(), + ) + + /** + * Returns sum of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun Int.plus(other: Symbol): LabeledPolynomial = + if (this == 0) LabeledPolynomialAsIs( + mapOf(other to 1U) to constantOne, + ) + else LabeledPolynomialAsIs( + mapOf(other to 1U) to constantOne, + emptyMap() to this@plus.asConstant(), + ) + /** + * Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun Int.minus(other: Symbol): LabeledPolynomial = + if (this == 0) LabeledPolynomialAsIs( + mapOf(other to 1U) to -constantOne, + ) + else LabeledPolynomialAsIs( + mapOf(other to 1U) to -constantOne, + emptyMap() to constantOne * this@minus, + ) + /** + * Returns product of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun Int.times(other: Symbol): LabeledPolynomial = + if (this == 0) zero + else LabeledPolynomialAsIs( + mapOf(other to 1U) to this@times.asConstant(), + ) + + /** + * Returns sum of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = + when { + other == 0 -> this + coefficients.isEmpty() -> other.asPolynomial() + else -> LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), other.asConstant()) { it -> it + other } + ) + } + /** + * Returns difference between the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = + when { + other == 0 -> this + coefficients.isEmpty() -> other.asPolynomial() + else -> LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), (-other).asConstant()) { it -> it - other } + ) + } + /** + * Returns product of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = + when(other) { + 0 -> zero + 1 -> this + else -> LabeledPolynomialAsIs( + coefficients.mapValues { (_, value) -> value * other } + ) + } + + /** + * Returns sum of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = + when { + this == 0 -> other + other.coefficients.isEmpty() -> this@plus.asPolynomial() + else -> LabeledPolynomialAsIs( + other.coefficients.withPutOrChanged(emptyMap(), this@plus.asConstant()) { it -> this@plus + it } + ) + } + /** + * Returns difference between the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = + when { + this == 0 -> -other + other.coefficients.isEmpty() -> this@minus.asPolynomial() + else -> LabeledPolynomialAsIs( + buildMap(other.coefficients.size + 1) { + put(emptyMap(), asConstant()) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) + } + ) + } + /** + * Returns product of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = + when(this) { + 0 -> zero + 1 -> other + else -> LabeledPolynomialAsIs( + other.coefficients.mapValues { (_, value) -> this@times * value } + ) + } + + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + public override operator fun Symbol.plus(other: C): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(this@plus to 1U) to constantOne, + emptyMap() to other, + ) + /** + * Returns difference between the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + public override operator fun Symbol.minus(other: C): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(this@minus to 1U) to constantOne, + emptyMap() to -other, + ) + /** + * Returns product of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + public override operator fun Symbol.times(other: C): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(this@times to 1U) to other, + ) + + /** + * Returns sum of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun C.plus(other: Symbol): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(other to 1U) to constantOne, + emptyMap() to this@plus, + ) + /** + * Returns difference between the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun C.minus(other: Symbol): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(other to 1U) to -constantOne, + emptyMap() to this@minus, + ) + /** + * Returns product of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + public override operator fun C.times(other: Symbol): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(other to 1U) to this@times, + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = + if (other.coefficients.isEmpty()) this@plus.asLabeledPolynomial() + else LabeledPolynomialAsIs( + other.coefficients.withPutOrChanged(emptyMap(), this@plus) { it -> this@plus + it } + ) + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = + if (other.coefficients.isEmpty()) this@minus.asPolynomial() + else LabeledPolynomialAsIs( + buildMap(other.coefficients.size + 1) { + put(emptyMap(), this@minus) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) + } + ) + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + other.coefficients.mapValues { this@times * it.value } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = + if (coefficients.isEmpty()) other.asLabeledPolynomial() + else LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), other) { it -> it + other } + ) + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = + if (coefficients.isEmpty()) other.asLabeledPolynomial() + else LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), -other) { it -> it - other } + ) + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = + LabeledPolynomialAsIs( + coefficients.mapValues { it.value * other } + ) + + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): LabeledPolynomial = value.asLabeledPolynomial() + + /** + * Represents the variable as a monic monomial. + */ + public override operator fun Symbol.unaryPlus(): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(this to 1U) to constantOne, + ) + /** + * Returns negation of representation of the variable as a monic monomial. + */ + public override operator fun Symbol.unaryMinus(): LabeledPolynomial = + LabeledPolynomialAsIs( + mapOf(this to 1U) to -constantOne, + ) + /** + * Returns sum of the variables represented as monic monomials. + */ + public override operator fun Symbol.plus(other: Symbol): LabeledPolynomial = + if (this == other) LabeledPolynomialAsIs( + mapOf(this to 1U) to constantOne * 2 + ) + else LabeledPolynomialAsIs( + mapOf(this to 1U) to constantOne, + mapOf(other to 1U) to constantOne, + ) + /** + * Returns difference between the variables represented as monic monomials. + */ + public override operator fun Symbol.minus(other: Symbol): LabeledPolynomial = + if (this == other) zero + else LabeledPolynomialAsIs( + mapOf(this to 1U) to constantOne, + mapOf(other to 1U) to -constantOne, + ) + /** + * Returns product of the variables represented as monic monomials. + */ + public override operator fun Symbol.times(other: Symbol): LabeledPolynomial = + if (this == other) LabeledPolynomialAsIs( + mapOf(this to 2U) to constantOne + ) + else LabeledPolynomialAsIs( + mapOf(this to 1U, other to 1U) to constantOne, + ) + + /** + * Returns sum of the variable represented as a monic monomial and the polynomial. + */ + public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = + if (other.coefficients.isEmpty()) this@plus.asPolynomial() + else LabeledPolynomialAsIs( + other.coefficients.withPutOrChanged(mapOf(this@plus to 1U), constantOne) { it -> constantOne + it } + ) + /** + * Returns difference between the variable represented as a monic monomial and the polynomial. + */ + public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = + if (other.coefficients.isEmpty()) this@minus.asPolynomial() + else LabeledPolynomialAsIs( + buildMap(other.coefficients.size + 1) { + put(mapOf(this@minus to 1U), constantOne) + other.coefficients.copyMapToBy(this, { _, c -> -c }) { currentC, newC -> currentC - newC } + } + ) + /** + * Returns product of the variable represented as a monic monomial and the polynomial. + */ + public override operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + other.coefficients + .mapKeys { (degs, _) -> degs.withPutOrChanged(this, 1u) { it -> it + 1u } } + ) + + /** + * Returns sum of the polynomial and the variable represented as a monic monomial. + */ + public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = + if (coefficients.isEmpty()) other.asPolynomial() + else LabeledPolynomialAsIs( + coefficients.withPutOrChanged(mapOf(other to 1U), constantOne) { it -> it + constantOne } + ) + /** + * Returns difference between the polynomial and the variable represented as a monic monomial. + */ + public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = + if (coefficients.isEmpty()) other.asPolynomial() + else LabeledPolynomialAsIs( + coefficients.withPutOrChanged(mapOf(other to 1U), -constantOne) { it -> it - constantOne } + ) + /** + * Returns product of the polynomial and the variable represented as a monic monomial. + */ + public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = + LabeledPolynomialAsIs( + coefficients + .mapKeys { (degs, _) -> degs.withPutOrChanged(other, 1u) { it -> it + 1u } } + ) + + /** + * Returns negation of the polynomial. + */ + override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = + LabeledPolynomialAsIs( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + buildMap(coefficients.size + other.coefficients.size) { + coefficients.copyTo(this) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + buildMap(coefficients.size * other.coefficients.size) { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = mergeBy(degs1, degs2) { deg1, deg2 -> deg1 + deg2 } + val c = c1 * c2 + this.putOrChange(degs, c) { it -> it + c } + } + } + ) + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: LabeledPolynomial = LabeledPolynomialAsIs() + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: LabeledPolynomial = constantOne.asLabeledPolynomial() + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + override val LabeledPolynomial.degree: Int + get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.values.sum().toInt() } ?: -1 + /** + * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents + * in which they are appeared in the polynomial. + * + * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. + * And keys of the map is the same as in [variables]. + */ + public override val LabeledPolynomial.degrees: Map + get() = + buildMap { + coefficients.keys.forEach { degs -> + degs.copyToBy(this, ::max) + } + } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public override fun LabeledPolynomial.degreeBy(variable: Symbol): UInt = + coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public override fun LabeledPolynomial.degreeBy(variables: Collection): UInt = + coefficients.entries.maxOfOrNull { (degs, _) -> degs.filterKeys { it in variables }.values.sum() } ?: 0u + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public override val LabeledPolynomial.variables: Set + get() = + buildSet { + coefficients.entries.forEach { (degs, _) -> addAll(degs.keys) } + } + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public override val LabeledPolynomial.countOfVariables: Int get() = variables.size + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + public inline fun LabeledPolynomial.substitute(arguments: Map): LabeledPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun LabeledPolynomial.substitute(arguments: Map>) : LabeledPolynomial = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt new file mode 100644 index 000000000..185782f22 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.operations.Ring +import kotlin.jvm.JvmName + + +/** + * Represents multivariate rational function that stores its numerator and denominator as [LabeledPolynomial]s. + */ +public data class LabeledRationalFunction( + public override val numerator: LabeledPolynomial, + public override val denominator: LabeledPolynomial +) : RationalFunction> { + override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +/** + * Arithmetic context for univariate rational functions with numerator and denominator represented as [LabeledPolynomial]s. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class LabeledRationalFunctionSpace>( + public val ring: A, +) : + MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace< + C, + Symbol, + LabeledPolynomial, + LabeledRationalFunction, + LabeledPolynomialSpace, + >, + MultivariatePolynomialSpaceOfFractions< + C, + Symbol, + LabeledPolynomial, + LabeledRationalFunction, + >() { + + /** + * Underlying polynomial ring. Its polynomial operations are inherited by local polynomial operations. + */ + override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) + /** + * Constructor of rational functions (of type [LabeledRationalFunction]) from numerator and denominator (of type [LabeledPolynomial]). + */ + override fun constructRationalFunction( + numerator: LabeledPolynomial, + denominator: LabeledPolynomial + ): LabeledRationalFunction = + LabeledRationalFunction(numerator, denominator) + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Substitutes provided constant [argument] into [this] polynomial. + */ + public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @JvmName("substituteRationalFunction") + public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + public inline fun LabeledRationalFunction.substitute(argument: Map): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @JvmName("substitutePolynomial") + public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @JvmName("substituteRationalFunction") + public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt new file mode 100644 index 000000000..3753a93c4 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -0,0 +1,374 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations +import space.kscience.kmath.operations.invoke +import kotlin.math.max +import kotlin.math.min + + +/** + * Represents univariate polynomial that stores its coefficients in a [List]. + * + * @param C the type of constants. + */ +public data class ListPolynomial( + /** + * List that contains coefficients of the polynomial. + * + * Every monomial \(a x^d\) is stored as a coefficient \(a\) placed + * into the list at index \(d\). For example, coefficients of a polynomial \(5 x^2 - 6\) can be represented as + * ``` + * listOf( + * -6, // -6 + + * 0, // 0 x + + * 5, // 5 x^2 + * ) + * ``` + * and also as + * ``` + * listOf( + * -6, // -6 + + * 0, // 0 x + + * 5, // 5 x^2 + * 0, // 0 x^3 + * 0, // 0 x^4 + * ) + * ``` + * It is not prohibited to put extra zeros at end of the list (as for \(0x^3\) and \(0x^4\) in the example). But the + * longer the coefficients list the worse performance of arithmetical operations performed on it. Thus, it is + * recommended not to put (or even to remove) extra (or useless) coefficients at the end of the coefficients list. + * @usesMathJax + */ + public val coefficients: List +) { + override fun toString(): String = "ListPolynomial$coefficients" +} + +/** + * Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the provided + * [ring] of constants. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public open class ListPolynomialSpace>( + public override val ring: A, +) : PolynomialSpaceOverRing, A> { + /** + * Returns sum of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun ListPolynomial.plus(other: Int): ListPolynomial = + if (other == 0) this + else + ListPolynomial( + coefficients + .toMutableList() + .apply { + val result = getOrElse(0) { constantZero } + other + + if(size == 0) add(result) + else this[0] = result + } + ) + /** + * Returns difference between the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun ListPolynomial.minus(other: Int): ListPolynomial = + if (other == 0) this + else + ListPolynomial( + coefficients + .toMutableList() + .apply { + val result = getOrElse(0) { constantZero } - other + + if(size == 0) add(result) + else this[0] = result + } + ) + /** + * Returns product of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun ListPolynomial.times(other: Int): ListPolynomial = + when (other) { + 0 -> zero + 1 -> this + else -> ListPolynomial( + coefficients.map { it * other } + ) + } + + /** + * Returns sum of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: ListPolynomial): ListPolynomial = + if (this == 0) other + else + ListPolynomial( + other.coefficients + .toMutableList() + .apply { + val result = this@plus + getOrElse(0) { constantZero } + + if(size == 0) add(result) + else this[0] = result + } + ) + /** + * Returns difference between the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: ListPolynomial): ListPolynomial = + ListPolynomial( + other.coefficients + .toMutableList() + .apply { + if (this@minus == 0) { + indices.forEach { this[it] = -this[it] } + } else { + (1..lastIndex).forEach { this[it] = -this[it] } + + val result = this@minus - getOrElse(0) { constantZero } + + if (size == 0) add(result) + else this[0] = result + } + } + ) + /** + * Returns product of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: ListPolynomial): ListPolynomial = + when (this) { + 0 -> zero + 1 -> other + else -> ListPolynomial( + other.coefficients.map { this@times * it } + ) + } + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public override operator fun C.plus(other: ListPolynomial): ListPolynomial = + with(other.coefficients) { + if (isEmpty()) ListPolynomial(listOf(this@plus)) + else ListPolynomial( + toMutableList() + .apply { + val result = if (size == 0) this@plus else this@plus + get(0) + + if(size == 0) add(result) + else this[0] = result + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public override operator fun C.minus(other: ListPolynomial): ListPolynomial = + with(other.coefficients) { + if (isEmpty()) ListPolynomial(listOf(this@minus)) + else ListPolynomial( + toMutableList() + .apply { + (1 .. lastIndex).forEach { this[it] = -this[it] } + + val result = if (size == 0) this@minus else this@minus - get(0) + + if(size == 0) add(result) + else this[0] = result + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + public override operator fun C.times(other: ListPolynomial): ListPolynomial = + ListPolynomial( + other.coefficients.map { this@times * it } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public override operator fun ListPolynomial.plus(other: C): ListPolynomial = + with(coefficients) { + if (isEmpty()) ListPolynomial(listOf(other)) + else ListPolynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) + other + + if(size == 0) add(result) + else this[0] = result + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public override operator fun ListPolynomial.minus(other: C): ListPolynomial = + with(coefficients) { + if (isEmpty()) ListPolynomial(listOf(-other)) + else ListPolynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) - other + + if(size == 0) add(result) + else this[0] = result + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + public override operator fun ListPolynomial.times(other: C): ListPolynomial = + ListPolynomial( + coefficients.map { it * other } + ) + + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): ListPolynomial = ListPolynomial(listOf(value)) + + /** + * Returns negation of the polynomial. + */ + public override operator fun ListPolynomial.unaryMinus(): ListPolynomial = + ListPolynomial(coefficients.map { -it }) + /** + * Returns sum of the polynomials. + */ + public override operator fun ListPolynomial.plus(other: ListPolynomial): ListPolynomial { + val thisDegree = degree + val otherDegree = other.degree + return ListPolynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] + } + } + ) + } + /** + * Returns difference of the polynomials. + */ + public override operator fun ListPolynomial.minus(other: ListPolynomial): ListPolynomial { + val thisDegree = degree + val otherDegree = other.degree + return ListPolynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> -other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] + } + } + ) + } + /** + * Returns product of the polynomials. + */ + public override operator fun ListPolynomial.times(other: ListPolynomial): ListPolynomial { + val thisDegree = degree + val otherDegree = other.degree + return ListPolynomial( + List(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) + } + /** + * Raises [arg] to the integer power [exponent]. + */ // TODO: To optimize boxing + override fun power(arg: ListPolynomial, exponent: UInt): ListPolynomial = super.power(arg, exponent) + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: ListPolynomial = ListPolynomial(emptyList()) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: ListPolynomial by lazy { ListPolynomial(listOf(constantOne)) } + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public override val ListPolynomial.degree: Int get() = coefficients.lastIndex + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunction(): (C) -> C = asFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = asFunctionOfConstantOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = asFunctionOfPolynomialOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) +} + +/** + * Space of polynomials constructed over ring. + * + * @param C the type of constants. Polynomials have them as a coefficients in their terms. + * @param A type of underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class ScalableListPolynomialSpace( + ring: A, +) : ListPolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { + override fun scale(a: ListPolynomial, value: Double): ListPolynomial = + ring { ListPolynomial(a.coefficients.map { scale(it, value) }) } +} diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt new file mode 100644 index 000000000..c2fa6b2ec --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring + + +/** + * Represents univariate rational function that stores its numerator and denominator as [ListPolynomial]s. + */ +public data class ListRationalFunction( + public override val numerator: ListPolynomial, + public override val denominator: ListPolynomial +) : RationalFunction> { + override fun toString(): String = "ListRationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +/** + * Arithmetic context for univariate rational functions with numerator and denominator represented as [ListPolynomial]s. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class ListRationalFunctionSpace> ( + public val ring: A, +) : + RationalFunctionSpaceOverPolynomialSpace< + C, + ListPolynomial, + ListRationalFunction, + ListPolynomialSpace, + >, + PolynomialSpaceOfFractions< + C, + ListPolynomial, + ListRationalFunction, + >() { + + /** + * Underlying polynomial ring. Its polynomial operations are inherited by local polynomial operations. + */ + override val polynomialRing : ListPolynomialSpace = ListPolynomialSpace(ring) + /** + * Constructor of [ListRationalFunction] from numerator and denominator [ListPolynomial]. + */ + override fun constructRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, denominator) + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Evaluates value of [this] polynomial on provided argument. + */ + public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunction(): (C) -> C = { substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + + /** + * Evaluates value of [this] polynomial on provided argument. + */ + public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt new file mode 100644 index 000000000..eaf5befb1 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -0,0 +1,350 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.Buffer +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents multivariate polynomial that stores its coefficients in a [Map] and terms' signatures in a [List]. + * + * @param C the type of constants. + */ +public data class NumberedPolynomial +@PublishedApi +internal constructor( + /** + * Map that contains coefficients of the polynomial. + * + * Every monomial \(a x_1^{d_1} ... x_n^{d_n}\) is stored as a pair "key-value" in the map, where the value is the + * coefficient \(a\) and the key is a list that associates index of every variable in the monomial with their degree + * in the monomial. For example, coefficients of a polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be represented as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, // 5 x_1^2 x_3^3 + + * listOf(0, 1) to (-6), // (-6) x_2^1 + * ) + * ``` + * and also as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, // 5 x_1^2 x_3^3 + + * listOf(0, 1) to (-6), // (-6) x_2^1 + * listOf(0, 1, 1) to 0, // 0 x_2^1 x_3^1 + * ) + * ``` + * It is not prohibited to put extra zero monomials into the map (as for \(0 x_2 x_3\) in the example). But the + * bigger the coefficients map the worse performance of arithmetical operations performed on it. Thus, it is + * recommended not to put (or even to remove) extra (or useless) monomials in the coefficients map. + * @usesMathJax + */ + public val coefficients: Map, C> +) { + override fun toString(): String = "NumberedPolynomial$coefficients" +} + +/** + * Arithmetic context for multivariate polynomials with coefficients stored as a [Map] and terms' signatures stored as a + * [List] constructed with the provided [ring] of constants. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class NumberedPolynomialSpace>( + public override val ring: A, +) : PolynomialSpaceOverRing, A> { + /** + * Returns sum of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun NumberedPolynomial.plus(other: Int): NumberedPolynomial = + if (other == 0) this + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), other.asConstant()) { it -> it + other } + ) + /** + * Returns difference between the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun NumberedPolynomial.minus(other: Int): NumberedPolynomial = + if (other == 0) this + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), (-other).asConstant()) { it -> it - other } + ) + /** + * Returns product of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = + when (other) { + 0 -> zero + 1 -> this + else -> NumberedPolynomialAsIs( + coefficients.mapValues { it.value * other } + ) + } + + /** + * Returns sum of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) other + else NumberedPolynomialAsIs( + other.coefficients.withPutOrChanged(emptyList(), this@plus.asConstant()) { it -> this@plus + it } + ) + /** + * Returns difference between the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: NumberedPolynomial): NumberedPolynomial = + when { + this == 0 -> -other + other.coefficients.isEmpty() -> this.asPolynomial() + else -> NumberedPolynomialAsIs( + buildMap(other.coefficients.size + 1) { + put(emptyList(), other.coefficients.computeOnOrElse(emptyList(), { this@minus.asConstant() }, { it -> this@minus - it})) + other.coefficients.copyMapToBy(this, { _, c -> -c }) { currentC, _ -> currentC } + } + ) + } + /** + * Returns product of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = + when (this) { + 0 -> zero + 1 -> other + else -> NumberedPolynomialAsIs( + other.coefficients.mapValues { this@times * it.value } + ) + } + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = + if (other.coefficients.isEmpty()) this@plus.asPolynomial() + else NumberedPolynomialAsIs( + other.coefficients.withPutOrChanged(emptyList(), this@plus) { it -> this@plus + it } + ) + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = + if (other.coefficients.isEmpty()) this@minus.asPolynomial() + else NumberedPolynomialAsIs( + buildMap(other.coefficients.size) { + put(emptyList(), other.coefficients.computeOnOrElse(emptyList(), this@minus) { it -> this@minus - it }) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, _ -> currentC }) + } + ) + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + other.coefficients.mapValues { this@times * it.value } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = + if (coefficients.isEmpty()) other.asPolynomial() + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), other) { it -> it + other } + ) + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = + if (coefficients.isEmpty()) other.asPolynomial() + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), -other) { it -> it - other } + ) + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = + NumberedPolynomialAsIs( + coefficients.mapValues { it.value * other } + ) + + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): NumberedPolynomial = + NumberedPolynomialAsIs(mapOf(emptyList() to value)) + + /** + * Returns negation of the polynomial. + */ + override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = + NumberedPolynomialAsIs( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + buildMap(coefficients.size + other.coefficients.size) { + coefficients.copyTo(this) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + buildMap(coefficients.size * other.coefficients.size) { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = + (0..max(degs1.lastIndex, degs2.lastIndex)) + .map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } } + val c = c1 * c2 + putOrChange(degs, c) { it -> it + c } + } + } + ) + /** + * Raises [arg] to the integer power [exponent]. + */ // TODO: To optimize boxing + override fun power(arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = super.power(arg, exponent) + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: NumberedPolynomial = NumberedPolynomialAsIs(emptyMap()) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: NumberedPolynomial by lazy { NumberedPolynomialAsIs(mapOf(emptyList() to constantOne)) } + + /** + * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, + * the result is -1. + */ + public val NumberedPolynomial.lastVariable: Int + get() = coefficients.keys.maxOfOrNull { degs -> degs.lastIndex } ?: -1 + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + override val NumberedPolynomial.degree: Int + get() = coefficients.keys.maxOfOrNull { degs -> degs.sum().toInt() } ?: -1 + /** + * List that associates indices of variables (that appear in the polynomial in positive exponents) with their most + * exponents in which the variables are appeared in the polynomial. + * + * As consequence all values in the list are non-negative integers. Also, if the polynomial is constant, the list is empty. + * And last index of the list is [lastVariable]. + */ + public val NumberedPolynomial.degrees: List + get() = + MutableList(lastVariable + 1) { 0u }.apply { + coefficients.keys.forEach { degs -> + degs.forEachIndexed { index, deg -> + this[index] = max(this[index], deg) + } + } + } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public fun NumberedPolynomial.degreeBy(variable: Int): UInt = + coefficients.keys.maxOfOrNull { degs -> degs.getOrElse(variable) { 0u } } ?: 0u + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = + coefficients.keys.maxOfOrNull { degs -> + degs.withIndex().fold(0u) { acc, (index, value) -> if (index in variables) acc + value else acc } + } ?: 0u + /** + * Count of variables occurring in the polynomial with positive power. If there is no such variable, + * the result is 0. + */ + public val NumberedPolynomial.countOfVariables: Int + get() = + MutableList(lastVariable + 1) { false }.apply { + coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + }.count { it } + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substitute(arguments: Map): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(arguments: Map>) : NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substitute(arguments: Buffer): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(arguments: Buffer>) : NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = this.substituteFully(ring, arguments) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [arguments]. + */ + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt new file mode 100644 index 000000000..4109338fd --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -0,0 +1,225 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents multivariate rational function that stores its numerator and denominator as [NumberedPolynomial]s. + */ +public data class NumberedRationalFunction( + public override val numerator: NumberedPolynomial, + public override val denominator: NumberedPolynomial +) : RationalFunction> { + override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +/** + * Arithmetic context for univariate rational functions with numerator and denominator represented as [NumberedPolynomial]s. + * + * @param C the type of constants. Polynomials have them a coefficients in their terms. + * @param A type of provided underlying ring of constants. It's [Ring] of [C]. + * @param ring underlying ring of constants of type [A]. + */ +public class NumberedRationalFunctionSpace> ( + public val ring: A, +) : + RationalFunctionSpaceOverPolynomialSpace< + C, + NumberedPolynomial, + NumberedRationalFunction, + NumberedPolynomialSpace, + >, + PolynomialSpaceOfFractions< + C, + NumberedPolynomial, + NumberedRationalFunction, + >() { + + /** + * Underlying polynomial ring. Its polynomial operations are inherited by local polynomial operations. + */ + public override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) + /** + * Constructor of rational functions (of type [NumberedRationalFunction]) from numerator and denominator (of type [NumberedPolynomial]). + */ + protected override fun constructRationalFunction( + numerator: NumberedPolynomial, + denominator: NumberedPolynomial + ): NumberedRationalFunction = + NumberedRationalFunction(numerator, denominator) + + /** + * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, + * the result is `-1`. + */ + public val NumberedPolynomial.lastVariable: Int get() = polynomialRing { lastVariable } + /** + * List that associates indices of variables (that appear in the polynomial in positive exponents) with their most + * exponents in which the variables are appeared in the polynomial. + * + * As consequence all values in the list are non-negative integers. Also, if the polynomial is constant, the list is empty. + * And last index of the list is [lastVariable]. + */ + public val NumberedPolynomial.degrees: List get() = polynomialRing { degrees } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public fun NumberedPolynomial.degreeBy(variable: Int): UInt = polynomialRing { degreeBy(variable) } + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = polynomialRing { degreeBy(variables) } + /** + * Count of variables occurring in the polynomial with positive power. If there is no such variable, + * the result is `0`. + */ + public val NumberedPolynomial.countOfVariables: Int get() = polynomialRing { countOfVariables } + + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val NumberedRationalFunction.lastVariable: Int + get() = polynomialRing { max(numerator.lastVariable, denominator.lastVariable) } + /** + * Count of variables occurring in the rational function with positive power. If there is no such variable, + * the result is `0`. + */ + public val NumberedRationalFunction.countOfVariables: Int + get() = + MutableList(lastVariable + 1) { false }.apply { + numerator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + denominator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + }.count { it } + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Substitutes provided constant [argument] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @JvmName("substituteRationalFunction") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + public inline fun NumberedRationalFunction.substitute(argument: Map): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @JvmName("substituteRationalFunction") + public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substitute(argument: Buffer): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @JvmName("substituteRationalFunction") + public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + public inline fun NumberedRationalFunction.substitute(argument: Buffer): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [arguments] into [this] rational function. + */ + @JvmName("substitutePolynomial") + public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided rational function [arguments] into [this] rational function. + */ + @JvmName("substituteRationalFunction") + public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided constant [arguments] into [this] polynomial. + */ + public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = substituteFully(ring, arguments) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedPolynomial.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedRationalFunction.asFunctionOfPolynomial(): (Buffer>) -> NumberedRationalFunction = asFunctionOfPolynomialOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun NumberedRationalFunction.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [arguments]. + */ + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @JvmName("invokeRationalFunction") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] rational function. + */ + @JvmName("invokePolynomial") + public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] rational function. + */ + @JvmName("invokeRationalFunction") + public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt new file mode 100644 index 000000000..7140ba70e --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -0,0 +1,527 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. + */ +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 +public interface PolynomialSpace : Ring

{ + /** + * Returns sum of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("plusConstantInt") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("minusConstantInt") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesConstantInt") + public operator fun C.times(other: Int): C + + /** + * Returns sum of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("plusIntConstant") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("minusIntConstant") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntConstant") + public operator fun Int.times(other: C): C + + /** + * Converts the integer [value] to constant. + */ + public fun constantNumber(value: Int): C = constantOne * value + /** + * Converts the integer to constant. + */ + public fun Int.asConstant(): C = constantNumber(this) + + /** + * Returns sum of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P = addMultipliedByDoubling(this, one, other) + /** + * Returns difference between the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P = addMultipliedByDoubling(this, one, -other) + /** + * Returns product of the polynomial and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P = multiplyByDoubling(this, other) + + /** + * Returns sum of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P = addMultipliedByDoubling(other, one, this) + /** + * Returns difference between the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P = addMultipliedByDoubling(-other, one, this) + /** + * Returns product of the integer represented as a polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P = multiplyByDoubling(other, this) + + /** + * Converts the integer [value] to polynomial. + */ + public fun number(value: Int): P = number(constantNumber(value)) + /** + * Converts the integer to polynomial. + */ + public fun Int.asPolynomial(): P = number(this) + + /** + * Returns the same constant. + */ + @JvmName("unaryPlusConstant") + @JsName("unaryPlusConstant") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("unaryMinusConstant") + @JsName("unaryMinusConstant") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("plusConstantConstant") + @JsName("plusConstantConstant") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("minusConstantConstant") + @JsName("minusConstantConstant") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("timesConstantConstant") + @JsName("timesConstantConstant") + public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerConstant") + @JsName("powerConstant") + public fun power(arg: C, exponent: UInt) : C + + /** + * Instance of zero constant (zero of the underlying ring). + */ + public val constantZero: C + /** + * Instance of unit constant (unit of the underlying ring). + */ + public val constantOne: C + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusConstantPolynomial") + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusConstantPolynomial") + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesConstantPolynomial") + public operator fun C.times(other: P): P + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusPolynomialConstant") + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusPolynomialConstant") + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesPolynomialConstant") + public operator fun P.times(other: C): P + + /** + * Converts the constant [value] to polynomial. + */ + public fun number(value: C): P = one * value + /** + * Converts the constant to polynomial. + */ + public fun C.asPolynomial(): P = number(this) + + /** + * Returns the same polynomial. + */ + public override operator fun P.unaryPlus(): P = this + /** + * Returns negation of the polynomial. + */ + public override operator fun P.unaryMinus(): P + /** + * Returns sum of the polynomials. + */ + public override operator fun P.plus(other: P): P + /** + * Returns difference of the polynomials. + */ + public override operator fun P.minus(other: P): P + /** + * Returns product of the polynomials. + */ + public override operator fun P.times(other: P): P + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: P, exponent: UInt) : P = exponentiateBySquaring(arg, exponent) + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + public override val zero: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + public override val one: P + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public val P.degree: Int + + override fun add(left: P, right: P): P = left + right + override fun multiply(left: P, right: P): P = left * right +} + +/** + * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. It also assumes that there is + * provided [ring] (of type [A]), that provides constant-wise operations. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. + * @param A the type of algebraic structure (precisely, of ring) provided for constants. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface PolynomialSpaceOverRing> : PolynomialSpace { + + /** + * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. + */ + public val ring: A + + /** + * Returns sum of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("plusConstantInt") + public override operator fun C.plus(other: Int): C = ring { addMultipliedByDoubling(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("minusConstantInt") + public override operator fun C.minus(other: Int): C = ring { addMultipliedByDoubling(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesConstantInt") + public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } + + /** + * Returns sum of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("plusIntConstant") + public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } + /** + * Returns difference between the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("minusIntConstant") + public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } + /** + * Returns product of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntConstant") + public override operator fun Int.times(other: C): C = ring { multiplyByDoubling(other, this@times) } + + /** + * Returns negation of the constant. + */ + @JvmName("unaryMinusConstant") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("plusConstantConstant") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("minusConstantConstant") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("timesConstantConstant") + public override operator fun C.times(other: C): C = ring { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerConstant") + override fun power(arg: C, exponent: UInt): C = ring { power(arg, exponent) } + + /** + * Instance of zero constant (zero of the underlying ring). + */ + public override val constantZero: C get() = ring.zero + /** + * Instance of unit constant (unit of the underlying ring). + */ + public override val constantOne: C get() = ring.one +} + +/** + * Abstraction of ring of polynomials of type [P] of variables of type [V] and over ring of constants of type [C]. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param V the type of variables. Polynomials have them in representations of terms. + * @param P the type of polynomials. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface MultivariatePolynomialSpace: PolynomialSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("plusVariableInt") + @JsName("plusVariableInt") + public operator fun V.plus(other: Int): P + /** + * Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("minusVariableInt") + @JsName("minusVariableInt") + public operator fun V.minus(other: Int): P + /** + * Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("timesVariableInt") + @JsName("timesVariableInt") + public operator fun V.times(other: Int): P + + /** + * Returns sum of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusIntVariable") + @JsName("plusIntVariable") + public operator fun Int.plus(other: V): P + /** + * Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusIntVariable") + @JsName("minusIntVariable") + public operator fun Int.minus(other: V): P + /** + * Returns product of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesIntVariable") + @JsName("timesIntVariable") + public operator fun Int.times(other: V): P + + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("plusVariableConstant") + @JsName("plusVariableConstant") + public operator fun V.plus(other: C): P + /** + * Returns difference between the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("minusVariableConstant") + @JsName("minusVariableConstant") + public operator fun V.minus(other: C): P + /** + * Returns product of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("timesVariableConstant") + @JsName("timesVariableConstant") + public operator fun V.times(other: C): P + + /** + * Returns sum of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusConstantVariable") + @JsName("plusConstantVariable") + public operator fun C.plus(other: V): P + /** + * Returns difference between the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusConstantVariable") + @JsName("minusConstantVariable") + public operator fun C.minus(other: V): P + /** + * Returns product of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesConstantVariable") + @JsName("timesConstantVariable") + public operator fun C.times(other: V): P + + /** + * Represents the variable as a monic monomial. + */ + @JvmName("unaryPlusVariable") + public operator fun V.unaryPlus(): P + /** + * Returns negation of representation of the variable as a monic monomial. + */ + @JvmName("unaryMinusVariable") + public operator fun V.unaryMinus(): P + /** + * Returns sum of the variables represented as monic monomials. + */ + @JvmName("plusVariableVariable") + public operator fun V.plus(other: V): P + /** + * Returns difference between the variables represented as monic monomials. + */ + @JvmName("minusVariableVariable") + public operator fun V.minus(other: V): P + /** + * Returns product of the variables represented as monic monomials. + */ + @JvmName("timesVariableVariable") + public operator fun V.times(other: V): P + + /** + * Represents the [variable] as a monic monomial. + */ + @JvmName("numberVariable") + public fun number(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + @JvmName("asPolynomialVariable") + public fun V.asPolynomial(): P = number(this) + + /** + * Returns sum of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("plusVariablePolynomial") + public operator fun V.plus(other: P): P + /** + * Returns difference between the variable represented as a monic monomial and the polynomial. + */ + @JvmName("minusVariablePolynomial") + public operator fun V.minus(other: P): P + /** + * Returns product of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("timesVariablePolynomial") + public operator fun V.times(other: P): P + + /** + * Returns sum of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusPolynomialVariable") + public operator fun P.plus(other: V): P + /** + * Returns difference between the polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusPolynomialVariable") + public operator fun P.minus(other: V): P + /** + * Returns product of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesPolynomialVariable") + public operator fun P.times(other: V): P + + /** + * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents + * in which they are appeared in the polynomial. + * + * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. + * And keys of the map is the same as in [variables]. + */ + public val P.degrees: Map + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public fun P.degreeBy(variable: V): UInt = degrees.getOrElse(variable) { 0u } + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun P.degreeBy(variables: Collection): UInt + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val P.variables: Set get() = degrees.keys + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val P.countOfVariables: Int get() = variables.size +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt new file mode 100644 index 000000000..766d9ce98 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -0,0 +1,1689 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of rational function. + */ +public interface RationalFunction { + public val numerator: P + public val denominator: P + public operator fun component1(): P = numerator + public operator fun component2(): P = denominator +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] and constants of type + * [C]. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators. + * @param R the type of rational functions. + */ +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 +public interface RationalFunctionSpace> : Ring { + /** + * Returns sum of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("plusConstantInt") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("minusConstantInt") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesConstantInt") + public operator fun C.times(other: Int): C + + /** + * Returns sum of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("plusIntConstant") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("minusIntConstant") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntConstant") + public operator fun Int.times(other: C): C + + /** + * Converts the integer [value] to constant. + */ + public fun constantNumber(value: Int): C = constantOne * value + /** + * Converts the integer to constant. + */ + public fun Int.asConstant(): C = constantNumber(this) + + /** + * Returns sum of the constant and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + @JvmName("plusPolynomialInt") + public operator fun P.plus(other: Int): P + /** + * Returns difference between the constant and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + @JvmName("minusPolynomialInt") + public operator fun P.minus(other: Int): P + /** + * Returns product of the constant and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesPolynomialInt") + public operator fun P.times(other: Int): P + + /** + * Returns sum of the integer represented as a polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + @JvmName("plusIntPolynomial") + public operator fun Int.plus(other: P): P + /** + * Returns difference between the integer represented as a polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + @JvmName("minusIntPolynomial") + public operator fun Int.minus(other: P): P + /** + * Returns product of the integer represented as a polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntPolynomial") + public operator fun Int.times(other: P): P + + /** + * Converts the integer [value] to polynomial. + */ + public fun polynomialNumber(value: Int): P = polynomialOne * value + /** + * Converts the integer to polynomial. + */ + public fun Int.asPolynomial(): P = polynomialNumber(this) + + /** + * Returns sum of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun R.plus(other: Int): R = addMultipliedByDoubling(this, one, other) + /** + * Returns difference between the rational function and the integer represented as a rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun R.minus(other: Int): R = addMultipliedByDoubling(this, one, -other) + /** + * Returns product of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun R.times(other: Int): R = multiplyByDoubling(this, other) + /** + * Returns quotient of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to creating a new rational function by preserving numerator of [this] and + * multiplication denominator of [this] to [other]. + */ + public operator fun R.div(other: Int): R = this / multiplyByDoubling(one, other) + + /** + * Returns sum of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: R): R = addMultipliedByDoubling(other, one, this) + /** + * Returns difference between the integer represented as a rational function and the rational function. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: R): R = addMultipliedByDoubling(-other, one, this) + /** + * Returns product of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: R): R = multiplyByDoubling(other, this) + /** + * Returns quotient of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to creating a new rational function which numerator is [this] times denominator of + * [other] and which denominator is [other]'s numerator. + */ + public operator fun Int.div(other: R): R = multiplyByDoubling(one / other, this) + + /** + * Converts the integer [value] to rational function. + */ + public fun number(value: Int): R = one * value + /** + * Converts the integer to rational function. + */ + public fun Int.asRationalFunction(): R = number(this) + + /** + * Returns the same constant. + */ + @JvmName("unaryPlusConstant") + @JsName("unaryPlusConstant") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("unaryMinusConstant") + @JsName("unaryMinusConstant") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("plusConstantConstant") + @JsName("plusConstantConstant") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("minusConstantConstant") + @JsName("minusConstantConstant") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("timesConstantConstant") + @JsName("timesConstantConstant") + public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerConstant") + @JsName("powerConstant") + public fun power(arg: C, exponent: UInt) : C + + /** + * Instance of zero constant (zero of the underlying ring). + */ + public val constantZero: C + /** + * Instance of unit constant (unit of the underlying ring). + */ + public val constantOne: C + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusConstantPolynomial") + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusConstantPolynomial") + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesConstantPolynomial") + public operator fun C.times(other: P): P + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusPolynomialConstant") + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusPolynomialConstant") + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesPolynomialConstant") + public operator fun P.times(other: C): P + + /** + * Converts the constant [value] to polynomial. + */ + public fun polynomialNumber(value: C): P = polynomialOne * value + /** + * Converts the constant to polynomial. + */ + public fun C.asPolynomial(): P = polynomialNumber(this) + + /** + * Returns the same polynomial. + */ + @JvmName("unaryPlusPolynomial") + public operator fun P.unaryPlus(): P = this + /** + * Returns negation of the polynomial. + */ + @JvmName("unaryMinusPolynomial") + public operator fun P.unaryMinus(): P + /** + * Returns sum of the polynomials. + */ + @JvmName("plusPolynomialPolynomial") + public operator fun P.plus(other: P): P + /** + * Returns difference of the polynomials. + */ + @JvmName("minusPolynomialPolynomial") + public operator fun P.minus(other: P): P + /** + * Returns product of the polynomials. + */ + @JvmName("timesPolynomialPolynomial") + public operator fun P.times(other: P): P + /** + * Returns quotient of the polynomials as rational function. + */ + @JvmName("divPolynomialPolynomial") + public operator fun P.div(other: P): R + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerPolynomial") + public fun power(arg: P, exponent: UInt) : P + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + public val polynomialZero: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + public val polynomialOne: P + + /** + * Returns sum of the constant represented as a rational function and the rational function. + */ + @JvmName("plusConstantRational") + public operator fun C.plus(other: R): R + /** + * Returns difference between the constant represented as a polynomial and the rational function. + */ + @JvmName("minusConstantRational") + public operator fun C.minus(other: R): R + /** + * Returns product of the constant represented as a polynomial and the rational function. + */ + @JvmName("timesConstantRational") + public operator fun C.times(other: R): R + /** + * Returns quotient of the constant represented as a polynomial and the rational function. + */ + @JvmName("divConstantRational") + public operator fun C.div(other: R): R + + /** + * Returns sum of the rational function and the constant represented as a rational function. + */ + @JvmName("plusRationalConstant") + public operator fun R.plus(other: C): R + /** + * Returns difference between the rational function and the constant represented as a rational function. + */ + @JvmName("minusRationalConstant") + public operator fun R.minus(other: C): R + /** + * Returns product of the rational function and the constant represented as a rational function. + */ + @JvmName("timesRationalConstant") + public operator fun R.times(other: C): R + /** + * Returns quotient of the rational function and the constant represented as a rational function. + */ + @JvmName("divRationalConstant") + public operator fun R.div(other: C): R + + /** + * Converts the constant [value] to rational function. + */ + @JvmName("numberConstant") + public fun number(value: C): R = one * value + /** + * Converts the constant to rational function. + */ + @JvmName("asRationalFunctionConstant") + public fun C.asRationalFunction(): R = number(this) + + /** + * Returns sum of the polynomial represented as a rational function and the rational function. + */ + @JvmName("plusPolynomialRational") + public operator fun P.plus(other: R): R + /** + * Returns difference between the polynomial represented as a polynomial and the rational function. + */ + @JvmName("minusPolynomialRational") + public operator fun P.minus(other: R): R + /** + * Returns product of the polynomial represented as a polynomial and the rational function. + */ + @JvmName("timesPolynomialRational") + public operator fun P.times(other: R): R + /** + * Returns quotient of the polynomial represented as a polynomial and the rational function. + */ + @JvmName("divPolynomialRational") + public operator fun P.div(other: R): R + + /** + * Returns sum of the rational function and the polynomial represented as a rational function. + */ + @JvmName("plusRationalPolynomial") + public operator fun R.plus(other: P): R + /** + * Returns difference between the rational function and the polynomial represented as a rational function. + */ + @JvmName("minusRationalPolynomial") + public operator fun R.minus(other: P): R + /** + * Returns product of the rational function and the polynomial represented as a rational function. + */ + @JvmName("timesRationalPolynomial") + public operator fun R.times(other: P): R + /** + * Returns quotient of the rational function and the polynomial represented as a rational function. + */ + @JvmName("divRationalPolynomial") + public operator fun R.div(other: P): R + + /** + * Converts the polynomial [value] to rational function. + */ + @JvmName("numberPolynomial") + public fun number(value: P): R = one * value + /** + * Converts the polynomial to rational function. + */ + @JvmName("asRationalFunctionPolynomial") + public fun P.asRationalFunction(): R = number(this) + + /** + * Returns the same rational function. + */ + public override operator fun R.unaryPlus(): R = this + /** + * Returns negation of the rational function. + */ + public override operator fun R.unaryMinus(): R + /** + * Returns sum of the rational functions. + */ + public override operator fun R.plus(other: R): R + /** + * Returns difference of the rational functions. + */ + public override operator fun R.minus(other: R): R + /** + * Returns product of the rational functions. + */ + public override operator fun R.times(other: R): R + /** + * Returns quotient of the rational functions. + */ + public operator fun R.div(other: R): R + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: R, exponent: UInt) : R = exponentiateBySquaring(arg, exponent) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: R + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: R + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public val P.degree: Int + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public val R.numeratorDegree: Int get() = numerator.degree + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public val R.denominatorDegree: Int get() = denominator.degree + + override fun add(left: R, right: R): R = left + right + override fun multiply(left: R, right: R): R = left * right +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] and constants of type + * [C]. It also assumes that there is provided [ring] (of type [A]), that provides constant-wise operations. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + * @param A the type of algebraic structure (precisely, of ring) provided for constants. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface RationalFunctionSpaceOverRing< + C, + P, + R: RationalFunction, + out A: Ring + > : RationalFunctionSpace { + + /** + * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. + */ + public val ring: A + + /** + * Returns sum of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("plusConstantInt") + public override operator fun C.plus(other: Int): C = ring { addMultipliedByDoubling(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("minusConstantInt") + public override operator fun C.minus(other: Int): C = ring { addMultipliedByDoubling(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesConstantInt") + public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } + + /** + * Returns sum of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("plusIntConstant") + public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } + /** + * Returns difference between the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("minusIntConstant") + public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } + /** + * Returns product of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntConstant") + public override operator fun Int.times(other: C): C = ring { multiplyByDoubling(other, this@times) } + + /** + * Returns the same constant. + */ + @JvmName("unaryPlusConstant") + public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("unaryMinusConstant") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("plusConstantConstant") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("minusConstantConstant") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("timesConstantConstant") + public override operator fun C.times(other: C): C = ring { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerConstant") + public override fun power(arg: C, exponent: UInt) : C = ring { power(arg, exponent) } + + /** + * Instance of zero constant (zero of the underlying ring). + */ + public override val constantZero: C get() = ring.zero + /** + * Instance of unit constant (unit of the underlying ring). + */ + public override val constantOne: C get() = ring.one +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] and constants of type + * [C]. It also assumes that there is provided [polynomialRing] (of type [AP]), that provides constant- and + * polynomial-wise operations. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface RationalFunctionSpaceOverPolynomialSpace< + C, + P, + R: RationalFunction, + out AP: PolynomialSpace, + > : RationalFunctionSpace { + + /** + * Underlying polynomial ring. Its polynomial operations are inherited by local polynomial operations. + */ + public val polynomialRing: AP + + /** + * Returns sum of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("plusConstantInt") + public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("minusConstantInt") + public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as a constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesConstantInt") + public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } + + /** + * Returns sum of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("plusIntConstant") + public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("minusIntConstant") + public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as a constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntConstant") + public override operator fun Int.times(other: C): C = polynomialRing { this@times * other } + + /** + * Converts the integer [value] to constant. + */ + public override fun constantNumber(value: Int): C = polynomialRing { constantNumber(value) } + /** + * Converts the integer to constant. + */ + override fun Int.asConstant(): C = polynomialRing { asConstant() } + + /** + * Returns sum of the constant and the integer represented as a polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + @JvmName("plusPolynomialInt") + public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as a polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + @JvmName("minusPolynomialInt") + public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as a polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("timesPolynomialInt") + public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } + + /** + * Returns sum of the integer represented as a polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + @JvmName("plusIntPolynomial") + public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as a polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + @JvmName("minusIntPolynomial") + public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as a polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("timesIntPolynomial") + public override operator fun Int.times(other: P): P = polynomialRing { this@times * other } + + /** + * Converts the integer [value] to polynomial. + */ + public override fun polynomialNumber(value: Int): P = polynomialRing { number(value) } + /** + * Converts the integer to polynomial. + */ + public override fun Int.asPolynomial(): P = polynomialRing { asPolynomial() } + + /** + * Returns the same constant. + */ + @JvmName("unaryPlusConstant") + public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("unaryMinusConstant") + public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("plusConstantConstant") + public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("minusConstantConstant") + public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("timesConstantConstant") + public override operator fun C.times(other: C): C = polynomialRing { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerConstant") + public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } + + /** + * Instance of zero constant (zero of the underlying ring). + */ + public override val constantZero: C get() = polynomialRing.constantZero + /** + * Instance of unit constant (unit of the underlying ring). + */ + public override val constantOne: C get() = polynomialRing.constantOne + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusConstantPolynomial") + public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusConstantPolynomial") + public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesConstantPolynomial") + public override operator fun C.times(other: P): P = polynomialRing { this@times * other } + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + @JvmName("plusPolynomialConstant") + public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + @JvmName("minusPolynomialConstant") + public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + @JvmName("timesPolynomialConstant") + public override operator fun P.times(other: C): P = polynomialRing { this@times * other } + + /** + * Converts the constant [value] to polynomial. + */ + public override fun polynomialNumber(value: C): P = polynomialRing { number(value) } + /** + * Converts the constant to polynomial. + */ + public override fun C.asPolynomial(): P = polynomialRing { asPolynomial() } + + /** + * Returns the same polynomial. + */ + @JvmName("unaryPlusPolynomial") + public override operator fun P.unaryPlus(): P = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the polynomial. + */ + @JvmName("unaryMinusPolynomial") + public override operator fun P.unaryMinus(): P = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the polynomials. + */ + @JvmName("plusPolynomialPolynomial") + public override operator fun P.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference of the polynomials. + */ + @JvmName("minusPolynomialPolynomial") + public override operator fun P.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the polynomials. + */ + @JvmName("timesPolynomialPolynomial") + public override operator fun P.times(other: P): P = polynomialRing { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("powerPolynomial") + public override fun power(arg: P, exponent: UInt) : P = polynomialRing { power(arg, exponent) } + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + public override val polynomialZero: P get() = polynomialRing.zero + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + public override val polynomialOne: P get() = polynomialRing.one + + /** + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. + */ + public override val P.degree: Int get() = polynomialRing { this@degree.degree } +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] and constants of type + * [C]. It also assumes that there is provided constructor [constructRationalFunction] of rational functions from + * polynomial numerator and denominator. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public abstract class PolynomialSpaceOfFractions< + C, + P, + R: RationalFunction, + > : RationalFunctionSpace { + + /** + * Constructor of rational functions (of type [R]) from numerator and denominator (of type [P]). + */ + protected abstract fun constructRationalFunction(numerator: P, denominator: P = polynomialOne) : R + + /** + * Returns sum of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun R.plus(other: Int): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the rational function and the integer represented as a rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun R.minus(other: Int): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun R.times(other: Int): R = + constructRationalFunction( + numerator * other, + denominator + ) + /** + * Returns quotient of the rational function and the integer represented as a rational function. + * + * The operation is equivalent to creating a new rational function by preserving numerator of [this] and + * multiplication denominator of [this] to [other]. + */ + public override operator fun R.div(other: Int): R = + constructRationalFunction( + numerator, + denominator * other + ) + + /** + * Returns sum of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the integer represented as a rational function and the rational function. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + /** + * Returns quotient of the integer represented as a rational function and the rational function. + * + * The operation is equivalent to creating a new rational function which numerator is [this] times denominator of + * [other] and which denominator is [other]'s numerator. + */ + public override operator fun Int.div(other: R): R = + constructRationalFunction( + this * other.denominator, + other.numerator + ) + + /** + * Converts the integer [value] to rational function. + */ + public override fun number(value: Int): R = constructRationalFunction(polynomialNumber(value)) + + /** + * Returns quotient of the polynomials as rational function. + */ + @JvmName("divPolynomialPolynomial") + public override operator fun P.div(other: P): R = constructRationalFunction(this, other) + + /** + * Returns sum of the constant represented as a rational function and the rational function. + */ + @JvmName("plusConstantRational") + public override operator fun C.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the constant represented as a polynomial and the rational function. + */ + @JvmName("minusConstantRational") + public override operator fun C.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the constant represented as a polynomial and the rational function. + */ + @JvmName("timesConstantRational") + public override operator fun C.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + /** + * Returns quotient of the constant represented as a polynomial and the rational function. + */ + @JvmName("divConstantRational") + public override operator fun C.div(other: R): R = + constructRationalFunction( + this * other.denominator, + other.numerator + ) + + /** + * Returns sum of the constant represented as a rational function and the rational function. + */ + @JvmName("plusRationalConstant") + public override operator fun R.plus(other: C): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as a rational function and the rational function. + */ + @JvmName("minusRationalConstant") + public override operator fun R.minus(other: C): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as a rational function and the rational function. + */ + @JvmName("timesRationalConstant") + public override operator fun R.times(other: C): R = + constructRationalFunction( + numerator * other, + denominator + ) + /** + * Returns quotient of the rational function and the constant represented as a rational function. + */ + @JvmName("divRationalConstant") + public override operator fun R.div(other: C): R = + constructRationalFunction( + numerator, + denominator * other + ) + + /** + * Converts the constant [value] to rational function. + */ + @JvmName("numberConstant") + public override fun number(value: C): R = constructRationalFunction(polynomialNumber(value)) + + /** + * Returns sum of the polynomial represented as a rational function and the rational function. + */ + @JvmName("plusPolynomialRational") + public override operator fun P.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the polynomial represented as a polynomial and the rational function. + */ + @JvmName("minusPolynomialRational") + public override operator fun P.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the polynomial represented as a polynomial and the rational function. + */ + @JvmName("timesPolynomialRational") + public override operator fun P.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + /** + * Returns quotient of the polynomial represented as a polynomial and the rational function. + */ + @JvmName("divPolynomialRational") + public override operator fun P.div(other: R): R = + constructRationalFunction( + this * other.denominator, + other.numerator + ) + + /** + * Returns sum of the polynomial represented as a rational function and the rational function. + */ + @JvmName("plusRationalPolynomial") + public override operator fun R.plus(other: P): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as a rational function and the rational function. + */ + @JvmName("minusRationalPolynomial") + public override operator fun R.minus(other: P): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as a rational function and the rational function. + */ + @JvmName("timesRationalPolynomial") + public override operator fun R.times(other: P): R = + constructRationalFunction( + numerator * other, + denominator + ) + /** + * Returns quotient of the rational function and the polynomial represented as a rational function. + */ + @JvmName("divRationalPolynomial") + public override operator fun R.div(other: P): R = + constructRationalFunction( + numerator, + denominator * other + ) + + /** + * Converts the polynomial [value] to rational function. + */ + @JvmName("numberPolynomial") + public override fun number(value: P): R = constructRationalFunction(value) + + /** + * Returns negation of the rational function. + */ + public override operator fun R.unaryMinus(): R = constructRationalFunction(-numerator, denominator) + /** + * Returns sum of the rational functions. + */ + public override operator fun R.plus(other: R): R = + constructRationalFunction( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns difference of the rational functions. + */ + public override operator fun R.minus(other: R): R = + constructRationalFunction( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns product of the rational functions. + */ + public override operator fun R.times(other: R): R = + constructRationalFunction( + numerator * other.numerator, + denominator * other.denominator + ) + /** + * Returns quotient of the rational functions. + */ + public override operator fun R.div(other: R): R = + constructRationalFunction( + numerator * other.denominator, + denominator * other.numerator + ) + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: R, exponent: UInt): R = + constructRationalFunction( + power(arg.numerator, exponent), + power(arg.denominator, exponent), + ) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: R by lazy { constructRationalFunction(polynomialZero) } + + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: R by lazy { constructRationalFunction(polynomialOne) } +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] of variables of type + * [V] and over ring of constants of type [C]. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param V the type of variables. Polynomials have them in representations of terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface MultivariateRationalFunctionSpace< + C, + V, + P, + R: RationalFunction + >: RationalFunctionSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("plusVariableInt") + @JsName("plusVariableInt") + public operator fun V.plus(other: Int): P + /** + * Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("minusVariableInt") + @JsName("minusVariableInt") + public operator fun V.minus(other: Int): P + /** + * Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("timesVariableInt") + @JsName("timesVariableInt") + public operator fun V.times(other: Int): P + + /** + * Returns sum of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusIntVariable") + @JsName("plusIntVariable") + public operator fun Int.plus(other: V): P + /** + * Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusIntVariable") + @JsName("minusIntVariable") + public operator fun Int.minus(other: V): P + /** + * Returns product of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesIntVariable") + @JsName("timesIntVariable") + public operator fun Int.times(other: V): P + + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("plusVariableConstant") + @JsName("plusVariableConstant") + public operator fun V.plus(other: C): P + /** + * Returns difference between the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("minusVariableConstant") + @JsName("minusVariableConstant") + public operator fun V.minus(other: C): P + /** + * Returns product of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("timesVariableConstant") + @JsName("timesVariableConstant") + public operator fun V.times(other: C): P + + /** + * Returns sum of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusConstantVariable") + @JsName("plusConstantVariable") + public operator fun C.plus(other: V): P + /** + * Returns difference between the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusConstantVariable") + @JsName("minusConstantVariable") + public operator fun C.minus(other: V): P + /** + * Returns product of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesConstantVariable") + @JsName("timesConstantVariable") + public operator fun C.times(other: V): P + + /** + * Represents the variable as a monic monomial. + */ + @JvmName("unaryPlusVariable") + @JsName("unaryPlusVariable") + public operator fun V.unaryPlus(): P + /** + * Returns negation of representation of the variable as a monic monomial. + */ + @JvmName("unaryMinusVariable") + @JsName("unaryMinusVariable") + public operator fun V.unaryMinus(): P + /** + * Returns sum of the variables represented as monic monomials. + */ + @JvmName("plusVariableVariable") + @JsName("plusVariableVariable") + public operator fun V.plus(other: V): P + /** + * Returns difference between the variables represented as monic monomials. + */ + @JvmName("minusVariableVariable") + @JsName("minusVariableVariable") + public operator fun V.minus(other: V): P + /** + * Returns product of the variables represented as monic monomials. + */ + @JvmName("timesVariableVariable") + @JsName("timesVariableVariable") + public operator fun V.times(other: V): P + + /** + * Represents the [variable] as a monic monomial. + */ + @JvmName("polynomialNumberVariable") + public fun polynomialNumber(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + @JvmName("asPolynomialVariable") + public fun V.asPolynomial(): P = polynomialNumber(this) + + /** + * Represents the [variable] as a rational function. + */ + @JvmName("numberVariable") + @JsName("numberVariable") + public fun number(variable: V): R = number(polynomialNumber(variable)) + /** + * Represents the variable as a rational function. + */ + @JvmName("asRationalFunctionVariable") + @JsName("asRationalFunctionVariable") + public fun V.asRationalFunction(): R = number(this) + + /** + * Returns sum of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("plusVariablePolynomial") + public operator fun V.plus(other: P): P + /** + * Returns difference between the variable represented as a monic monomial and the polynomial. + */ + @JvmName("minusVariablePolynomial") + public operator fun V.minus(other: P): P + /** + * Returns product of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("timesVariablePolynomial") + public operator fun V.times(other: P): P + + /** + * Returns sum of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusPolynomialVariable") + public operator fun P.plus(other: V): P + /** + * Returns difference between the polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusPolynomialVariable") + public operator fun P.minus(other: V): P + /** + * Returns product of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesPolynomialVariable") + public operator fun P.times(other: V): P + + /** + * Returns sum of the variable represented as a rational function and the rational function. + */ + @JvmName("plusVariableRational") + public operator fun V.plus(other: R): R + /** + * Returns difference between the variable represented as a rational function and the rational function. + */ + @JvmName("minusVariableRational") + public operator fun V.minus(other: R): R + /** + * Returns product of the variable represented as a rational function and the rational function. + */ + @JvmName("timesVariableRational") + public operator fun V.times(other: R): R + + /** + * Returns sum of the rational function and the variable represented as a rational function. + */ + @JvmName("plusRationalVariable") + public operator fun R.plus(other: V): R + /** + * Returns difference between the rational function and the variable represented as a rational function. + */ + @JvmName("minusRationalVariable") + public operator fun R.minus(other: V): R + /** + * Returns product of the rational function and the variable represented as a rational function. + */ + @JvmName("timesRationalVariable") + public operator fun R.times(other: V): R + + /** + * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents + * in which they are appeared in the polynomial. + * + * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. + * And keys of the map is the same as in [variables]. + */ + public val P.degrees: Map + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public fun P.degreeBy(variable: V): UInt = degrees.getOrElse(variable) { 0u } + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun P.degreeBy(variables: Collection): UInt + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val P.variables: Set get() = degrees.keys + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val P.countOfVariables: Int get() = variables.size + + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val R.variables: Set get() = numerator.variables union denominator.variables + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val R.countOfVariables: Int get() = variables.size +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] of variables of type + * [V] and over ring of constants of type [C]. It also assumes that there is provided [polynomialRing] (of type [AP]), + * that provides constant-, variable- and polynomial-wise operations. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param V the type of variables. Polynomials have them in representations of terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace< + C, + V, + P, + R: RationalFunction, + out AP: MultivariatePolynomialSpace, + > : RationalFunctionSpaceOverPolynomialSpace, MultivariateRationalFunctionSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("plusVariableInt") + public override operator fun V.plus(other: Int): P = polynomialRing { this@plus + other } + /** + * Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("minusVariableInt") + public override operator fun V.minus(other: Int): P = polynomialRing { this@minus - other } + /** + * Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ + @JvmName("timesVariableInt") + public override operator fun V.times(other: Int): P = polynomialRing { this@times * other } + + /** + * Returns sum of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusIntVariable") + public override operator fun Int.plus(other: V): P = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusIntVariable") + public override operator fun Int.minus(other: V): P = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesIntVariable") + public override operator fun Int.times(other: V): P = polynomialRing { this@times * other } + + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("plusVariableConstant") + public override operator fun V.plus(other: C): P = polynomialRing { this@plus + other } + /** + * Returns difference between the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("minusVariableConstant") + public override operator fun V.minus(other: C): P = polynomialRing { this@minus - other } + /** + * Returns product of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ + @JvmName("timesVariableConstant") + public override operator fun V.times(other: C): P = polynomialRing { this@times * other } + + /** + * Returns sum of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusConstantVariable") + public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusConstantVariable") + public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as a constant polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesConstantVariable") + public override operator fun C.times(other: V): P = polynomialRing { this@times * other } + + /** + * Represents the variable as a monic monomial. + */ + @JvmName("unaryPlusVariable") + public override operator fun V.unaryPlus(): P = polynomialRing { +this@unaryPlus } + /** + * Returns negation of representation of the variable as a monic monomial. + */ + @JvmName("unaryMinusVariable") + public override operator fun V.unaryMinus(): P = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the variables represented as monic monomials. + */ + @JvmName("plusVariableVariable") + public override operator fun V.plus(other: V): P = polynomialRing { this@plus + other } + /** + * Returns difference between the variables represented as monic monomials. + */ + @JvmName("minusVariableVariable") + public override operator fun V.minus(other: V): P = polynomialRing { this@minus - other } + /** + * Returns product of the variables represented as monic monomials. + */ + @JvmName("timesVariableVariable") + public override operator fun V.times(other: V): P = polynomialRing { this@times * other } + + /** + * Represents the [variable] as a monic monomial. + */ + @JvmName("polynomialNumberVariable") + public override fun polynomialNumber(variable: V): P = polynomialRing { number(variable) } + /** + * Represents the variable as a monic monomial. + */ + @JvmName("asPolynomialVariable") + public override fun V.asPolynomial(): P = polynomialRing { this@asPolynomial.asPolynomial() } + + /** + * Returns sum of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("plusVariablePolynomial") + public override operator fun V.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the variable represented as a monic monomial and the polynomial. + */ + @JvmName("minusVariablePolynomial") + public override operator fun V.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the variable represented as a monic monomial and the polynomial. + */ + @JvmName("timesVariablePolynomial") + public override operator fun V.times(other: P): P = polynomialRing { this@times * other } + + /** + * Returns sum of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("plusPolynomialVariable") + public override operator fun P.plus(other: V): P = polynomialRing { this@plus + other } + /** + * Returns difference between the polynomial and the variable represented as a monic monomial. + */ + @JvmName("minusPolynomialVariable") + public override operator fun P.minus(other: V): P = polynomialRing { this@minus - other } + /** + * Returns product of the polynomial and the variable represented as a monic monomial. + */ + @JvmName("timesPolynomialVariable") + public override operator fun P.times(other: V): P = polynomialRing { this@times * other } + + /** + * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents + * in which they are appeared in the polynomial. + * + * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. + * And keys of the map is the same as in [variables]. + */ + public override val P.degrees: Map get() = polynomialRing { degrees } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public override fun P.degreeBy(variable: V): UInt = polynomialRing { degreeBy(variable) } + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public override fun P.degreeBy(variables: Collection): UInt = polynomialRing { degreeBy(variables) } + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public override val P.variables: Set get() = polynomialRing { variables } + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public override val P.countOfVariables: Int get() = polynomialRing { countOfVariables } +} + +/** + * Abstraction of field of rational functions of type [R] with respect to polynomials of type [P] of variables of type + * [V] and over ring of constants of type [C]. It also assumes that there is provided constructor + * [constructRationalFunction] of rational functions from polynomial numerator and denominator. + * + * @param C the type of constants. Polynomials have them as coefficients in their terms. + * @param V the type of variables. Polynomials have them in representations of terms. + * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. + * @param R the type of rational functions. + */ +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 +public abstract class MultivariatePolynomialSpaceOfFractions< + C, + V, + P, + R: RationalFunction, + > : MultivariateRationalFunctionSpace, PolynomialSpaceOfFractions() { + /** + * Returns sum of the variable represented as a rational function and the rational function. + */ + @JvmName("plusVariableRational") + public override operator fun V.plus(other: R): R = + constructRationalFunction( + this * other.denominator + other.numerator, + other.denominator + ) + /** + * Returns difference between the variable represented as a rational function and the rational function. + */ + @JvmName("minusVariableRational") + public override operator fun V.minus(other: R): R = + constructRationalFunction( + this * other.denominator - other.numerator, + other.denominator + ) + /** + * Returns product of the variable represented as a rational function and the rational function. + */ + @JvmName("timesVariableRational") + public override operator fun V.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + + /** + * Returns sum of the rational function and the variable represented as a rational function. + */ + @JvmName("plusRationalVariable") + public override operator fun R.plus(other: V): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the rational function and the variable represented as a rational function. + */ + @JvmName("minusRationalVariable") + public override operator fun R.minus(other: V): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the rational function and the variable represented as a rational function. + */ + public override operator fun R.times(other: V): R = + constructRationalFunction( + numerator * other, + denominator + ) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt new file mode 100644 index 000000000..80bf6ec53 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.operations.* + + +// TODO: All of this should be moved to algebraic structures' place for utilities +// FIXME: Move receiver to context receiver +/** + * Returns product of [arg] and integer [multiplier]. + * + * @param arg the multiplicand. + * @param multiplier the integer multiplier. + * @return product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal fun Group.multiplyByDoubling(arg: C, multiplier: Int): C = + if (multiplier >= 0) multiplyByDoubling(arg, multiplier.toUInt()) + else multiplyByDoubling(-arg, (-multiplier).toUInt()) + +// FIXME: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the integer multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal fun GroupOps.addMultipliedByDoubling(base: C, arg: C, multiplier: Int): C = + if (multiplier >= 0) addMultipliedByDoubling(base, arg, multiplier.toUInt()) + else addMultipliedByDoubling(base, -arg, (-multiplier).toUInt()) + +// FIXME: Move receiver to context receiver +/** + * Returns product of [arg] and integer [multiplier]. + * + * This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) + * + * @param arg the multiplicand. + * @param multiplier the integer multiplier. + * @return product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun Group.multiplyByDoubling(arg: C, multiplier: UInt): C = + when { + multiplier == 0u -> zero + multiplier == 1u -> arg + multiplier and 1u == 0u -> multiplyByDoubling(arg + arg, multiplier shr 1) + multiplier and 1u == 1u -> addMultipliedByDoubling(arg, arg + arg, multiplier shr 1) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } + +// FIXME: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) + * + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the integer multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun GroupOps.addMultipliedByDoubling(base: C, arg: C, multiplier: UInt): C = + when { + multiplier == 0u -> base + multiplier == 1u -> base + arg + multiplier and 1u == 0u -> addMultipliedByDoubling(base, arg + arg, multiplier shr 1) + multiplier and 1u == 1u -> addMultipliedByDoubling(base + arg, arg + arg, multiplier shr 1) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } + +// FIXME: Move receiver to context receiver +/** + * Raises [arg] to the integer power [exponent]. + * + * @param arg the base of the power. + * @param exponent the exponent of the power. + * @return [arg] raised to the power [exponent]. + * @author Gleb Minaev + */ +internal fun Field.exponentiateBySquaring(arg: C, exponent: Int): C = + if (exponent >= 0) exponentiateBySquaring(arg, exponent.toUInt()) + else exponentiateBySquaring(one / arg, (-exponent).toUInt()) + +// FIXME: Move receiver to context receiver +/** + * Multiplies [base] and [arg] raised to the integer power [exponent]. + * + * @param base the multiplicand. + * @param arg the base of the power. + * @param exponent the exponent of the power. + * @return product of [base] and [arg] raised to the power [exponent]. + * @author Gleb Minaev + */ +internal fun Field.multiplyExponentiatedBySquaring(base: C, arg: C, exponent: Int): C = + if (exponent >= 0) multiplyExponentiatedBySquaring(base, arg, exponent.toUInt()) + else multiplyExponentiatedBySquaring(base, one / arg, (-exponent).toUInt()) + +// FIXME: Move receiver to context receiver +/** + * Raises [arg] to the integer power [exponent]. + * + * This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) + * + * @param arg the base of the power. + * @param exponent the exponent of the power. + * @return [arg] raised to the power [exponent]. + * @author Gleb Minaev + */ +internal tailrec fun Ring.exponentiateBySquaring(arg: C, exponent: UInt): C = + when { + exponent == 0u -> zero + exponent == 1u -> arg + exponent and 1u == 0u -> exponentiateBySquaring(arg * arg, exponent shr 1) + exponent and 1u == 1u -> multiplyExponentiatedBySquaring(arg, arg * arg, exponent shr 1) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } + +// FIXME: Move receiver to context receiver +/** + * Multiplies [base] and [arg] raised to the integer power [exponent]. + * + * This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) + * + * @param base the multiplicand. + * @param arg the base of the power. + * @param exponent the exponent of the power. + * @return product of [base] and [arg] raised to the power [exponent]. + * @author Gleb Minaev + */ +internal tailrec fun RingOps.multiplyExponentiatedBySquaring(base: C, arg: C, exponent: UInt): C = + when { + exponent == 0u -> base + exponent == 1u -> base * arg + exponent and 1u == 0u -> multiplyExponentiatedBySquaring(base, arg * arg, exponent shr 1) + exponent and 1u == 1u -> multiplyExponentiatedBySquaring(base * arg, arg * arg, exponent shr 1) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt new file mode 100644 index 000000000..e294f3533 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt @@ -0,0 +1,906 @@ +/* + * Copyright 2018-2022 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.functions + +import kotlin.contracts.InvocationKind.* +import kotlin.contracts.contract + + +/** + * Computes the given lambda [compute] on value corresponding to the provided [key] or `null` if the key is not present. + * + * @param key key which corresponding value will be used if it's present. + * @param compute lambda that is computed on the received value. + * @return result of the computation of the lambda. + */ +internal inline fun Map.computeOn(key: K, compute: (V?) -> R): R { + contract { + callsInPlace(compute, EXACTLY_ONCE) + } + return compute(get(key)) +} + +/** + * Computes the given lambda [compute] on value corresponding to the provided [key] or computes the given lambda + * [defaultResult] if the key is not present. + * + * @param key key which corresponding value will be used if it's present. + * @param compute lambda that is computed on the value corresponding to the [key]. + * @param defaultResult lambda that is computed if the [key] is not present. + * @return result of [compute] lambda if the [key] is present or result of [defaultResult] otherwise. + */ +internal inline fun Map.computeOnOrElse(key: K, defaultResult: () -> R, compute: (value: V) -> R): R { + contract { + callsInPlace(defaultResult, AT_MOST_ONCE) + callsInPlace(compute, AT_MOST_ONCE) + } + @Suppress("UNCHECKED_CAST") + return (if (key !in this) defaultResult() else compute(get(key) as V)) +} + +/** + * Computes the given lambda [compute] on value corresponding to the provided [key] or computes the given lambda + * [defaultResult] if the key is not present. + * + * @param key key which corresponding value will be used if it's present. + * @param compute lambda that is computed on the value corresponding to the [key]. + * @param defaultResult default result that is returned in case of the [key]'s absence. + * @return result of [compute] lambda if the [key] is present or [defaultResult] otherwise. + */ +internal inline fun Map.computeOnOrElse(key: K, defaultResult: R, compute: (value: V) -> R): R { + contract { + callsInPlace(compute, AT_MOST_ONCE) + } + return computeOnOrElse(key, { defaultResult }, compute) +} + +/** + * Computes the given lambda [compute] on value corresponding to the provided [key] or computes the given lambda + * [defaultResult] if the key is not present. + * + * @param key key which corresponding value will be used if it's present. + * @param compute lambda that is computed on the value corresponding to the [key]. + * @param defaultResult default result that is returned in case of the [key]'s absence. + * @return result of [compute] lambda if the [key] is present or [defaultResult] otherwise. + */ +internal inline fun Map.computeOnOrElse(key: K, defaultResult: R, compute: (key: K, value: V) -> R): R { + contract { + callsInPlace(compute, AT_MOST_ONCE) + } + return computeOnOrElse(key, { defaultResult }, { it -> compute(key, it) }) +} + +/** + * Applies the [transformation][transform] to the value corresponding to the given [key] or null instead if it's not + * present. + * + * @param key key to check. + * @param transform transformation to apply. + * @return result of the transformation + */ +internal inline fun MutableMap.applyToKey(key: K, transform: (currentValue: V?) -> V): V { + contract { + callsInPlace(transform, EXACTLY_ONCE) + } + return computeOn(key, transform).also { this[key] = it } +} + +/** + * Depending on presence of value corresponding to the given [key] either puts new value calculated by [valueOnPut] or + * changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut lazily calculated value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value as a parameter. + * @return result value corresponding to the [key]. + */ +internal inline fun MutableMap.putOrChange(key: K, valueOnPut: () -> V, transformOnChange: (currentValue: V) -> V): V { + contract { + callsInPlace(valueOnPut, AT_MOST_ONCE) + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return computeOnOrElse(key, valueOnPut, transformOnChange).also { this[key] = it } +} + +/** + * Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or + * changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value as a parameter. + * @return result value corresponding to the [key]. + */ +internal inline fun MutableMap.putOrChange(key: K, valueOnPut: V, transformOnChange: (currentValue: V) -> V): V { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return putOrChange(key, { valueOnPut }, transformOnChange) +} + +/** + * Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or + * changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value and new value as parameters. + * @return result value corresponding to the [key]. + */ +internal inline fun MutableMap.putOrChange(key: K, valueOnPut: V, transformOnChange: (currentValue: V, newValue: V) -> V): V { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return putOrChange(key, { valueOnPut }, { transformOnChange(it, valueOnPut) }) +} + +/** + * Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or + * changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * the [key], current value, and new value as parameters. + * @return result value corresponding to the [key]. + */ +internal inline fun MutableMap.putOrChange(key: K, valueOnPut: V, transformOnChange: (key: K, currentValue: V, newValue: V) -> V): V { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return putOrChange(key, { valueOnPut }, { transformOnChange(key, it, valueOnPut) }) +} + +/** + * Creates copy of [the map][this] and applies the [transformation][transform] to the value corresponding to the given + * [key] in the copy or null instead if it's not present. + * + * @param key key to check. + * @param transform transformation to apply. + * @return the copy of [the map][this]. + */ +internal inline fun Map.withAppliedToKey(key: K, transform: (currentValue: V?) -> V): Map { + contract { + callsInPlace(transform, EXACTLY_ONCE) + } + return buildMap(size) { + putAll(this) + applyToKey(key, transform) + } +} + +/** + * Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new + * value calculated by [valueOnPut] or changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut lazily calculated value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value as a parameter. + * @return the copy of [the map][this]. + */ +internal inline fun Map.withPutOrChanged(key: K, valueOnPut: () -> V, transformOnChange: (currentValue: V) -> V): Map { + contract { + callsInPlace(valueOnPut, AT_MOST_ONCE) + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return buildMap(size + 1) { + putAll(this@withPutOrChanged) + putOrChange(key, valueOnPut, transformOnChange) + } +} + +/** + * Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new + * value [valueOnPut] or changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value as a parameter. + * @return the copy of [the map][this]. + */ +internal inline fun Map.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (currentValue: V) -> V): Map { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return withPutOrChanged(key, { valueOnPut }, transformOnChange) +} + +/** + * Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new + * value [valueOnPut] or changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * current value and new value as parameters. + * @return the copy of [the map][this]. + */ +internal inline fun Map.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (currentValue: V, newValue: V) -> V): Map { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return withPutOrChanged(key, { valueOnPut }, { transformOnChange(it, valueOnPut) }) +} + +/** + * Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new + * value [valueOnPut] or changes the present value with [transformOnChange]. + * + * @param key key to check. + * @param valueOnPut value to put in case of absence of the [key]. + * @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses + * the [key], current value, and new value as parameters. + * @return the copy of [the map][this]. + */ +internal inline fun Map.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (key: K, currentValue: V, newValue: V) -> V): Map { + contract { + callsInPlace(transformOnChange, AT_MOST_ONCE) + } + return withPutOrChanged(key, { valueOnPut }, { transformOnChange(key, it, valueOnPut) }) +} + +/** + * Copies entries of [this map][this] to the [destination] map overriding present ones if needed. + * + * @receiver map to be copied. + * @param destination map to receive copies. + * @return the [destination]. + */ +internal fun > Map.copyTo(destination: D): D { + for ((key, value) in this) { + destination[key] = value + } + return destination +} + +/** + * Copies entries of [this map][this] to the [destination] map merging present entries with new ones using [resolve] + * lambda. + * + * @receiver map to be copied. + * @param destination map to receive copies. + * @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyToBy(destination: D, resolve: (key: K, currentValue: W, newValue: V) -> W): D { + for ((key, value) in this) { + destination.putOrChange(key, value) { it -> resolve(key, it, value) } + } + return destination +} + +/** + * Copies entries of [this map][this] to the [destination] map merging present entries with new ones using [resolve] + * lambda. + * + * @receiver map to be copied. + * @param destination map to receive copies. + * @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyToBy(destination: D, resolve: (currentValue: W, newValue: V) -> W): D = + copyToBy(destination) { _, currentValue, newValue -> resolve(currentValue, newValue) } + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map overriding present ones if needed. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyTo(destination) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @return the [destination]. + */ +internal inline fun > Map.copyMapTo(destination: D, transform: (Map.Entry) -> W): D { + for (entry in this) { + destination[entry.key] = transform(entry) + } + return destination +} + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map overriding present ones if needed. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyTo(destination) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @return the [destination]. + */ +internal inline fun > Map.copyMapTo(destination: D, transform: (key: K, value: V) -> W): D = + copyMapTo(destination) { (key, value) -> transform(key, value) } + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyToBy(destination, resolve) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyMapToBy(destination: D, transform: (Map.Entry) -> W, resolve: (key: K, currentValue: W, newValue: V) -> W): D { + for (entry in this) { + val (key, value) = entry + destination.putOrChange(key, transform(entry)) { it -> resolve(key, it, value) } + } + return destination +} + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyToBy(destination, resolve) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyMapToBy(destination: D, transform: (key: K, value: V) -> W, resolve: (key: K, currentValue: W, newValue: V) -> W): D = + copyMapToBy(destination, { (key, value) -> transform(key, value) }, resolve) + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyToBy(destination, resolve) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyMapToBy(destination: D, transform: (Map.Entry) -> W, resolve: (currentValue: W, newValue: V) -> W): D = + copyMapToBy(destination, transform, { _, currentValue, newValue -> resolve(currentValue, newValue) }) + +/** + * Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting + * entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to + * ```kotlin + * this.mapValues(transform).copyToBy(destination, resolve) + * ``` + * + * @receiver map to be transformed and copied. + * @param destination map to receive copies. + * @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is + * the same as initial entry. + * @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and + * a new one and returns value to associate to the key. + * @return the [destination]. + */ +internal inline fun > Map.copyMapToBy(destination: D, transform: (key: K, value: V) -> W, resolve: (currentValue: W, newValue: V) -> W): D = + copyMapToBy(destination, { (key, value) -> transform(key, value) }, { _, currentValue, newValue -> resolve(currentValue, newValue) }) + +/** + * Merges [the first map][map1] and [the second map][map2] prioritising the second one, puts result to the [destination] + * and returns the [destination]. + * + * Precisely, corresponding keys and values of the received maps are put into the destination overriding existing values + * in the [destination] if needed. For every key appearing in both maps corresponding value from the second map is + * chosen. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @param destination the map where result of the merge is put. + * @return the destination. + */ +internal fun > mergeTo(map1: Map, map2: Map, destination: D): D { + for ((key, value) in map1) { + destination.put(key, value) + } + for ((key, value) in map2) { + destination.put(key, value) + } + return destination +} + +/** + * Merges [the first map][map1] and [the second map][map2] resolving conflicts with [resolve] lambda, puts result to the + * [destination] and returns the [destination]. + * + * Precisely, corresponding keys and values of the received maps are put into the destination overriding existing values + * in the [destination] if needed. For every key appearing in both maps corresponding value is a result of the [resolve] + * lambda calculated on the key and its corresponding values from the merged maps. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @param resolve lambda function that resolves merge conflicts. + * @param destination the map where result of the merge is put. + * @return the destination. + */ +internal inline fun > mergeToBy(map1: Map, map2: Map, destination: D, resolve: (key: K, value1: V1, value2: V2) -> W): D { + for (key in map2.keys) { + destination.remove(key) + } + for ((key, value) in map1) { + destination.put(key, value) + } + for ((key, value) in map2) { + @Suppress("UNCHECKED_CAST") + destination.putOrChange(key, value) { it -> resolve(key, it as V1, value) } + } + return destination +} + +/** + * Merges [the first map][map1] and [the second map][map2] resolving conflicts with [resolve] lambda, puts result to the + * [destination] and returns the [destination]. + * + * Precisely, corresponding keys and values of the received maps are put into the destination overriding existing values + * in the [destination] if needed. For every key appearing in both maps corresponding value is a result of the [resolve] + * lambda calculated on the key's corresponding values from the merged maps. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @param resolve lambda function that resolves merge conflicts. + * @param destination the map where result of the merge is put. + * @return the destination. + */ +internal inline fun > mergeToBy(map1: Map, map2: Map, destination: D, resolve: (value1: V1, value2: V2) -> W): D = + mergeToBy(map1, map2, destination) { _, value1, value2 -> resolve(value1, value2) } + +/** + * Merges [the first map][map1] and [the second map][map2] prioritising the second one. + * + * Precisely, corresponding keys and values of the received maps are put into a new empty map which is returned after + * afterwards. For every key appearing in both maps corresponding value from the second map is chosen. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @return the result of the merge. + */ +internal fun merge(map1: Map, map2: Map): Map { + val result = LinkedHashMap(map1.size + map2.size) + return mergeTo(map1, map2, result) +} + +/** + * Merges [the first map][map1] and [the second map][map2] resolving conflicts with [resolve] lambda. + * + * Precisely, corresponding keys and values of the received maps are put into a new empty map which is returned after + * afterwards. For every key appearing in both maps corresponding value is a result of the [resolve] lambda calculated + * on the key and its corresponding values from the merged maps. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @param resolve lambda function that resolves merge conflicts. + * @return the result of the merge. + */ +internal inline fun mergeBy(map1: Map, map2: Map, resolve: (key: K, value1: V1, value2: V2) -> W): Map { + val result = LinkedHashMap(map1.size + map2.size) + return mergeToBy(map1, map2, result, resolve) +} + +/** + * Merges [the first map][map1] and [the second map][map2] resolving conflicts with [resolve] lambda. + * + * Precisely, corresponding keys and values of the received maps are put into a new empty map which is returned after + * afterwards. For every key appearing in both maps corresponding value is a result of the [resolve] lambda calculated + * on the key's corresponding values from the merged maps. + * + * @param map1 the first (less prioritised) map to merge. + * @param map2 the second (more prioritised) map to merge. + * @param resolve lambda function that resolves merge conflicts. + * @return the result of the merge. + */ +internal inline fun mergeBy(map1: Map, map2: Map, resolve: (value1: V1, value2: V2) -> W): Map = + mergeBy(map1, map2) { _, value1, value2 -> resolve(value1, value2) } + +/** + * Populates the [destination] map with key-value pairs provided by [transform] function applied to each element of the + * given collection resolving conflicts with [resolve] function and returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each element to key-value. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateTo(destination: D, transform: (T) -> Pair, resolve: (key: K, currentValue: V, newValue: V) -> V): D { + for (element in this) { + val (key, value) = transform(element) + destination.putOrChange(key, value, resolve) + } + return destination +} + +/** + * Populates the [destination] map with key-value pairs, where key is provided by [keySelector] function and value is + * provided by [valueTransform] applied to each element of the given collection, resolving conflicts with [resolve] + * function and returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param valueTransform lambda functions that generates value for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateByTo(destination: D, keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (key: K, currentValue: V, newValue: V) -> V): D { + for (element in this) { + val key = keySelector(element) + val value = valueTransform(element) + destination.putOrChange(key, value, resolve) + } + return destination +} + +/** + * Populates the [destination] map with key-value pairs, where key is provided by [keySelector] function applied to each + * element of the given collection and value is the element itself, resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateByTo(destination: D, keySelector: (T) -> K, resolve: (key: K, currentValue: T, newValue: T) -> T): D { + for (element in this) { + val key = keySelector(element) + destination.putOrChange(key, element, resolve) + } + return destination +} + +/** + * Populates the [destination] map with key-value pairs provided by [transform] function applied to each element of the + * given collection resolving conflicts with [resolve] function and returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each element to key-value pair. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateTo(destination: D, transform: (T) -> Pair, resolve: (currentValue: V, newValue: V) -> V): D = + associateTo(destination, transform) { _, currentValue, newValue -> resolve(currentValue, newValue) } + +/** + * Populates the [destination] map with key-value pairs, where key is provided by [keySelector] function and value is + * provided by [valueTransform] applied to each element of the given collection, resolving conflicts with [resolve] + * function and returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param valueTransform lambda functions that generates value for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateByTo(destination: D, keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (currentValue: V, newValue: V) -> V): D = + associateByTo(destination, keySelector, valueTransform) { _, currentValue, newValue -> resolve(currentValue, newValue) } + +/** + * Populates the [destination] map with key-value pairs, where key is provided by [keySelector] function applied to each + * element of the given collection and value is the element itself, resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Iterable.associateByTo(destination: D, keySelector: (T) -> K, resolve: (currentValue: T, newValue: T) -> T): D = + associateByTo(destination, keySelector) { _, currentValue, newValue -> resolve(currentValue, newValue) } + +/** + * Returns a map containing key-value pairs provided by [transform] function applied to elements of the given collection. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with the + * key is resolved with [resolve] function which takes the key, current value corresponding to the key, and new value + * from the pair. + * + * @param transform function which transforms each element to key-value pair. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associate(transform: (T) -> Pair, resolve: (key: K, currentValue: V, newValue: V) -> V): Map = + associateTo(LinkedHashMap(), transform, resolve) + +/** + * Returns a map containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to + * elements of the given collection. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with + * the key is resolved with [resolve] function which takes the key, current value corresponding to the key, and new + * value from the pair. + * + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param valueTransform lambda functions that generates value for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (key: K, currentValue: V, newValue: V) -> V): Map = + associateByTo(LinkedHashMap(), keySelector, valueTransform, resolve) + +/** + * Returns a map containing the elements from the given collection indexed by the key returned from [keySelector] + * function applied to each element. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with + * the key is resolved with [resolve] function which takes the key, current value corresponding to the key, and new + * value from the pair. + * + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associateBy(keySelector: (T) -> K, resolve: (key: K, currentValue: T, newValue: T) -> T): Map = + associateByTo(LinkedHashMap(), keySelector, resolve) + +/** + * Returns a map containing key-value pairs provided by [transform] function applied to elements of the given collection. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with + * the key is resolved with [resolve] function which takes current value corresponding to the key and new value from the + * pair. + * + * @param transform function which transforms each element to key-value pair. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associate(transform: (T) -> Pair, resolve: (currentValue: V, newValue: V) -> V): Map = + associateTo(LinkedHashMap(), transform, resolve) + +/** + * Returns a map containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to + * elements of the given collection. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with + * the key is resolved with [resolve] function which takes current value corresponding to the key and new value from the + * pair. + * + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param valueTransform lambda functions that generates value for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (currentValue: V, newValue: V) -> V): Map = + associateByTo(LinkedHashMap(), keySelector, valueTransform, resolve) + +/** + * Returns a map containing the elements from the given collection indexed by the key returned from [keySelector] + * function applied to each element. + * + * All pairs are added in order of iteration. If some key is already added to the map, adding new key-value pair with + * the key is resolved with [resolve] function which takes current value corresponding to the key and new value from the + * pair. + * + * @param keySelector lambda functions that generates keys for the key-value pairs. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Iterable.associateBy(keySelector: (T) -> K, resolve: (currentValue: T, newValue: T) -> T): Map = + associateByTo(LinkedHashMap(), keySelector, resolve) + +/** + * Populates the given [destination] map with entries having the keys of this map and the values obtained + * by applying the [transform] function to each entry in this map resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new value. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Map.mapValuesTo(destination: D, transform: (Map.Entry) -> W, resolve: (key: K, currentValue: W, newValue: W) -> W): D = + entries.associateByTo(destination, { it.key }, transform, resolve) + +/** + * Populates the given [destination] map with entries having the keys of this map and the values obtained + * by applying the [transform] function to each entry in this map resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new value. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Map.mapValuesTo(destination: D, transform: (key: K, value: V) -> W, resolve: (key: K, currentValue: W, newValue: W) -> W): D = + entries.associateByTo(destination, { it.key }, { (key, value) -> transform(key, value) }, resolve) + +/** + * Populates the given [destination] map with entries having the keys of this map and the values obtained + * by applying the [transform] function to each entry in this map resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new value. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the [destination]. + */ +internal inline fun > Map.mapValuesTo(destination: D, transform: (Map.Entry) -> W, resolve: (currentValue: W, newValue: W) -> W): D = + entries.associateByTo(destination, { it.key }, transform, resolve) + +/** + * Populates the given [destination] map with entries having the keys of this map and the values obtained + * by applying the [transform] function to each entry in this map resolving conflicts with [resolve] function and + * returns the [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new value. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the [destination]. + */ +internal inline fun > Map.mapValuesTo(destination: D, transform: (key: K, value: V) -> W, resolve: (currentValue: W, newValue: W) -> W): D = + entries.associateByTo(destination, { it.key }, { (key, value) -> transform(key, value) }, resolve) + +/** + * Populates the given [destination] map with entries having the keys obtained by applying the [transform] function to + * each entry in this map and the values of this map, resolving conflicts with [resolve] function and returns the + * [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Map.mapKeysTo(destination: D, transform: (Map.Entry) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): D = + entries.associateByTo(destination, transform, { it.value }, resolve) + +/** + * Populates the given [destination] map with entries having the keys obtained by applying the [transform] function to + * each entry in this map and the values of this map, resolving conflicts with [resolve] function and returns the + * [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the [destination]. + */ +internal inline fun > Map.mapKeysTo(destination: D, transform: (key: K, value: V) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): D = + entries.associateByTo(destination, { (key, value) -> transform(key, value) }, { it.value }, resolve) + +/** + * Populates the given [destination] map with entries having the keys obtained by applying the [transform] function to + * each entry in this map and the values of this map, resolving conflicts with [resolve] function and returns the + * [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the [destination]. + */ +internal inline fun > Map.mapKeysTo(destination: D, transform: (Map.Entry) -> L, resolve: (currentValue: V, newValue: V) -> V): D = + entries.associateByTo(destination, transform, { it.value }, resolve) + +/** + * Populates the given [destination] map with entries having the keys obtained by applying the [transform] function to + * each entry in this map and the values of this map, resolving conflicts with [resolve] function and returns the + * [destination]. + * + * All pairs are added and resolved in order of iteration. + * + * @param destination the destination of the generated key-value pairs. + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the [destination]. + */ +internal inline fun > Map.mapKeysTo(destination: D, transform: (key: K, value: V) -> L, resolve: (currentValue: V, newValue: V) -> V): D = + entries.associateByTo(destination, { (key, value) -> transform(key, value) }, { it.value }, resolve) + +/** + * Returns a new map with entries having the keys obtained by applying the [transform] function to each entry in this + * map and the values of this map and resolving conflicts with [resolve] function. + * + * All pairs are added and resolved in order of iteration. + * + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Map.mapKeys(transform: (Map.Entry) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) + +/** + * Returns a new map with entries having the keys obtained by applying the [transform] function to each entry in this + * map and the values of this map and resolving conflicts with [resolve] function. + * + * All pairs are added and resolved in order of iteration. + * + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which receives some key, its current, and new + * corresponding values. + * @return the result map. + */ +internal inline fun Map.mapKeys(transform: (key: K, value: V) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) + +/** + * Returns a new map with entries having the keys obtained by applying the [transform] function to each entry in this + * map and the values of this map and resolving conflicts with [resolve] function. + * + * All pairs are added and resolved in order of iteration. + * + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the result map. + */ +internal inline fun Map.mapKeys(transform: (Map.Entry) -> L, resolve: (currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) + +/** + * Returns a new map with entries having the keys obtained by applying the [transform] function to each entry in this + * map and the values of this map and resolving conflicts with [resolve] function. + * + * All pairs are added and resolved in order of iteration. + * + * @param transform function which transforms each key-value pair to new key. + * @param resolve lambda function that resolves merge conflicts which current and new values corresponding to some key. + * @return the result map. + */ +internal inline fun Map.mapKeys(transform: (key: K, value: V) -> L, resolve: (currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt new file mode 100644 index 000000000..78bb3b290 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -0,0 +1,779 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("FunctionName", "NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke + + +/** + * Returns the same degrees' description of the monomial, but without zero degrees. + */ +internal fun Map.cleanUp() = filterValues { it > 0U } + +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. The map is used as is. + */ +@PublishedApi +internal inline fun LabeledPolynomialAsIs(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs) + +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * The collections will be transformed to map with [toMap] and then will be used as is. + */ +@PublishedApi +internal inline fun LabeledPolynomialAsIs(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs.toMap()) + +/** + * Constructs [LabeledPolynomial] with provided array of [pairs] of pairs "term's signature — term's coefficient". + * The array will be transformed to map with [toMap] and then will be used as is. + */ +@PublishedApi +internal inline fun LabeledPolynomialAsIs(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toMap()) + +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. The map is used as is. + * + * **Be sure you read description of [LabeledPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun LabeledPolynomialWithoutCheck(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs) + +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * The collections will be transformed to map with [toMap] and then will be used as is. + * + * **Be sure you read description of [LabeledPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun LabeledPolynomialWithoutCheck(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs.toMap()) + +/** + * Constructs [LabeledPolynomial] with provided array of [pairs] of pairs "term's signature — term's coefficient". + * The array will be transformed to map with [toMap] and then will be used as is. + * + * **Be sure you read description of [LabeledPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun LabeledPolynomialWithoutCheck(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toMap()) + +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public fun LabeledPolynomial(coefs: Map, C>, add: (C, C) -> C) : LabeledPolynomial = + LabeledPolynomialAsIs( + coefs.mapKeys({ key, _ -> key.cleanUp() }, add) + ) + +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public fun LabeledPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : LabeledPolynomial = + LabeledPolynomialAsIs( + pairs.associateBy({ it.first.cleanUp() }, { it.second }, add) + ) + +/** + * Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public fun LabeledPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : LabeledPolynomial = + LabeledPolynomialAsIs( + pairs.asIterable().associateBy({ it.first.cleanUp() }, { it.second }, add) + ) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, ::add) +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs) { left: C, right: C -> left + right } + +/** + * Constructs [LabeledPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs) { left: C, right: C -> left + right } + +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, ::add) + +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs) { left: C, right: C -> left + right } +/** + * Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs) { left: C, right: C -> left + right } + +/** + * Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs) { left: C, right: C -> left + right } +/** + * Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs) { left: C, right: C -> left + right } +/** + * Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see LabeledPolynomialWithoutCheck + */ +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs) { left: C, right: C -> left + right } + +/** + * Converts [this] constant to [LabeledPolynomial]. + */ +public inline fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomialAsIs(mapOf(emptyMap() to this)) + +///** +//// * Converts [this] variable to [LabeledPolynomial]. +//// */ +//context(A) +//public inline fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) +///** +// * Converts [this] variable to [LabeledPolynomial]. +// */ +//context(LabeledPolynomialSpace) +//public inline fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) +///** +// * Converts [this] variable to [LabeledPolynomial]. +// */ +//context(LabeledRationalFunctionSpace) +//public inline fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +/** + * Marks DSL that allows to more simply create [LabeledPolynomial]s with good performance. + * + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as + * ``` + * Int.algebra { + * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { + * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + + * (-6) { b inPowerOf 1u } // (-6) b^1 + * } + * } + * ``` + * @usesMathJax + */ +@DslMarker +@UnstableKMathAPI +internal annotation class LabeledPolynomialConstructorDSL1 + +/** + * Builder of [LabeledPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. + */ +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL1 +public class DSL1LabeledPolynomialTermSignatureBuilder { + /** + * Signature storage. Any declaration of any variable's power updates the storage by increasing corresponding value. + * Afterward the storage will be used as a resulting signature. + */ + private val signature: MutableMap = LinkedHashMap() + + /** + * Builds the resulting signature. + * + * In fact, it just returns [signature] as regular signature of type `List`. + */ + @PublishedApi + internal fun build(): Map = signature + + /** + * Declares power of [this] variable of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public infix fun Symbol.inPowerOf(deg: UInt) { + if (deg == 0u) return + signature.putOrChange(this, deg) { it -> it + deg } + } + /** + * Declares power of [this] variable of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Symbol.pow(deg: UInt): Unit = this inPowerOf deg + /** + * Declares power of [this] variable of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Symbol.`in`(deg: UInt): Unit = this inPowerOf deg + /** + * Declares power of [this] variable of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg +} + +/** + * Builder of [LabeledPolynomial]. It should be used as an implicit context for lambdas that describe [LabeledPolynomial]. + */ +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL1 +public class DSL1LabeledPolynomialBuilder( + /** + * Summation operation that will be used to sum coefficients of monomials of same signatures. + */ + private val add: (C, C) -> C, + /** + * Initial capacity of coefficients map. + */ + initialCapacity: Int? = null +) { + /** + * Coefficients storage. Any declaration of any monomial updates the storage. + * Afterward the storage will be used as a resulting coefficients map. + */ + private val coefficients: MutableMap, C> = if (initialCapacity != null) LinkedHashMap(initialCapacity) else LinkedHashMap() + + /** + * Builds the resulting coefficients map. + * + * In fact, it just returns [coefficients] as regular coefficients map of type `Map, C>`. + */ + @PublishedApi + internal fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) + + /** + * Declares monomial with [this] coefficient and provided [signature]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public infix fun C.with(signature: Map) { + coefficients.putOrChange(signature, this@with, add) + } + /** + * Declares monomial with [this] coefficient and signature constructed by [block]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public inline infix fun C.with(noinline block: DSL1LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + /** + * Declares monomial with [this] coefficient and signature constructed by [block]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public inline operator fun C.invoke(block: DSL1LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = + this with DSL1LabeledPolynomialTermSignatureBuilder().apply(block).build() +} + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +///** +// * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of constants. +// * +// * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as +// * ``` +// * Int.algebra { +// * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { +// * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + +// * (-6) { b inPowerOf 1u } // (-6) b^1 +// * } +// * } +// * ``` +// * @usesMathJax +// */ +// FIXME: For now this fabric does not let next two fabrics work. (See KT-52803.) Possible feature solutions: +// 1. `LowPriorityInOverloadResolution` becomes public. Then it should be applied to this function. +// 2. Union types are implemented. Then all three functions should be rewritten +// as one with single union type as a (context) receiver. +//@UnstableKMathAPI +//public inline fun > A.LabeledPolynomialDSL1(initialCapacity: Int? = null, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(::add, initialCapacity).apply(block).build() +/** + * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of [LabeledPolynomial]s. + * + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as + * ``` + * Int.algebra { + * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { + * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + + * (-6) { b inPowerOf 1u } // (-6) b^1 + * } + * } + * ``` + * @usesMathJax + */ +@UnstableKMathAPI +public inline fun > LabeledPolynomialSpace.LabeledPolynomialDSL1(initialCapacity: Int? = null, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +/** + * Creates [LabeledPolynomial] with lambda [block] in context of [this] field of [LabeledRationalFunction]s. + * + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as + * ``` + * Int.algebra { + * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { + * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + + * (-6) { b inPowerOf 1u } // (-6) b^1 + * } + * } + * ``` + * @usesMathJax + */ +@UnstableKMathAPI +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomialDSL1(initialCapacity: Int? = null, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() + +/** + * Marks DSL that allows to more simply create [LabeledPolynomial]s with good performance. + * + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + + * (-6) { b inPowerOf 1u } // (-6) b^1 + * } + * } + * ``` + * @usesMathJax + */ +@DslMarker +@UnstableKMathAPI +internal annotation class LabeledPolynomialBuilderDSL2 + +/** + * Builder of [LabeledPolynomial]. It should be used as an implicit context for lambdas that describe [LabeledPolynomial]. + */ +@UnstableKMathAPI +@LabeledPolynomialBuilderDSL2 +public class DSL2LabeledPolynomialBuilder( + private val ring: Ring, + /** + * Initial capacity of coefficients map. + */ + initialCapacity: Int? = null +) { + /** + * Coefficients storage. Any declaration of any monomial updates the storage. + * Afterward the storage will be used as a resulting coefficients map. + */ + private val coefficients: MutableMap, C> = if (initialCapacity != null) LinkedHashMap(initialCapacity) else LinkedHashMap() + + /** + * Builds the resulting coefficients map. + * + * In fact, it just returns [coefficients] as regular coefficients map of type `Map, C>`. + */ + @PublishedApi + internal fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) + + public inner class Term internal constructor( + internal val signature: Map = HashMap(), + internal val coefficient: C + ) + + private inline fun submit(signature: Map, onPut: Ring.() -> C, onChange: Ring.(C) -> C) { + coefficients.putOrChange<_, C>(signature, { ring.onPut() }, { ring.onChange(it) }) + } + + private inline fun submit(signature: Map, lazyCoefficient: Ring.() -> C) { + submit(signature, lazyCoefficient) { it + lazyCoefficient() } + } + + private fun submit(signature: Map, coefficient: C) { + submit(signature) { coefficient } + } + + // TODO: `@submit` will be resolved differently. Change it to `@C`. + private fun C.submitSelf() = submit(emptyMap()) { this@submitSelf } + + private fun Symbol.submit() = submit(mapOf(this to 1u)) { one } + + private fun Term.submit(): Submit { + submit(signature, coefficient) + return Submit + } + + public object Submit + + public operator fun C.unaryPlus(): Submit { + submitSelf() + return Submit + } + + public operator fun C.unaryMinus(): Submit { + submit(emptyMap(), { -this@unaryMinus }, { it - this@unaryMinus }) + return Submit + } + + public operator fun C.plus(other: C): Submit { + submit(emptyMap()) { this@plus + other } + return Submit + } + + public operator fun C.minus(other: C): Submit { + submit(emptyMap()) { this@minus - other } + return Submit + } + + public operator fun C.times(other: C): C = ring { this@times * other } + + public operator fun C.plus(other: Symbol): Submit { + submit(emptyMap(), this) + submit(mapOf(other to 1u), ring.one) + return Submit + } + + public operator fun C.minus(other: Symbol): Submit { + submit(emptyMap(), this) + submit(mapOf(other to 1u), { -one }, { it - one }) + return Submit + } + + public operator fun C.times(other: Symbol): Term = Term(mapOf(other to 1u), this) + + public operator fun C.plus(other: Term): Submit { + submit(emptyMap(), this) + other.submit() + return Submit + } + + public operator fun C.minus(other: Term): Submit { + submit(emptyMap(), this) + submit(other.signature, { -other.coefficient }, { it - other.coefficient }) + return Submit + } + + public operator fun C.times(other: Term): Term = Term(other.signature, ring { this@times * other.coefficient }) + + public operator fun Symbol.plus(other: C): Submit { + this.submit() + other.submitSelf() + return Submit + } + + public operator fun Symbol.minus(other: C): Submit { + this.submit() + submit(emptyMap(), { -other }, { it - other }) + return Submit + } + + public operator fun Symbol.times(other: C): Term = Term(mapOf(this to 1u), other) + + public operator fun Symbol.unaryPlus(): Submit { + this.submit() + return Submit + } + + public operator fun Symbol.unaryMinus(): Submit { + submit(mapOf(this to 1u), { -one }, { it - one }) + return Submit + } + + public operator fun Symbol.plus(other: Symbol): Submit { + this.submit() + other.submit() + return Submit + } + + public operator fun Symbol.minus(other: Symbol): Submit { + this.submit() + submit(mapOf(other to 1u), { -one }, { it - one }) + return Submit + } + + public operator fun Symbol.times(other: Symbol): Term = + if (this == other) Term(mapOf(this to 2u), ring.one) + else Term(mapOf(this to 1u, other to 1u), ring.one) + + public operator fun Symbol.plus(other: Term): Submit { + this.submit() + other.submit() + return Submit + } + + public operator fun Symbol.minus(other: Term): Submit { + this.submit() + submit(other.signature, { -other.coefficient }, { it - other.coefficient }) + return Submit + } + + public operator fun Symbol.times(other: Term): Term = + Term( + other.signature.withPutOrChanged(this, 1u) { it -> it + 1u }, + other.coefficient + ) + + public operator fun Term.plus(other: C): Submit { + this.submit() + other.submitSelf() + return Submit + } + + public operator fun Term.minus(other: C): Submit { + this.submit() + submit(emptyMap(), { -other }, { it - other }) + return Submit + } + + public operator fun Term.times(other: C): Term = + Term( + signature, + ring { coefficient * other } + ) + + public operator fun Term.plus(other: Symbol): Submit { + this.submit() + other.submit() + return Submit + } + + public operator fun Term.minus(other: Symbol): Submit { + this.submit() + submit(mapOf(other to 1u), { -one }, { it - one }) + return Submit + } + + public operator fun Term.times(other: Symbol): Term = + Term( + signature.withPutOrChanged(other, 1u) { it -> it + 1u }, + coefficient + ) + + public operator fun Term.unaryPlus(): Submit { + this.submit() + return Submit + } + + public operator fun Term.unaryMinus(): Submit { + submit(signature, { -coefficient }, { it - coefficient }) + return Submit + } + + public operator fun Term.plus(other: Term): Submit { + this.submit() + other.submit() + return Submit + } + + public operator fun Term.minus(other: Term): Submit { + this.submit() + submit(other.signature, { -other.coefficient }, { it - other.coefficient }) + return Submit + } + + public operator fun Term.times(other: Term): Term = + Term( + mergeBy(signature, other.signature) { deg1, deg2 -> deg1 + deg2 }, + ring { coefficient * other.coefficient } + ) +} + +//@UnstableKMathAPI +//public fun Ring.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder.() -> Unit): LabeledPolynomial = DSL2LabeledPolynomialBuilder(this, initialCapacity).apply(block).build() + +@UnstableKMathAPI +public fun > LabeledPolynomialSpace.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder.() -> Unit): LabeledPolynomial = DSL2LabeledPolynomialBuilder(ring, initialCapacity).apply(block).build() + +@UnstableKMathAPI +public fun > LabeledRationalFunctionSpace.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder.() -> Unit): LabeledPolynomial = DSL2LabeledPolynomialBuilder(ring, initialCapacity).apply(block).build() + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [LabeledRationalFunction] with provided coefficients maps [numeratorCoefficients] and [denominatorCoefficients]. + * + * The maps will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. the maps' keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(denominatorCoefficients) + ) +/** + * Constructs [LabeledRationalFunction] with provided coefficients maps [numeratorCoefficients] and [denominatorCoefficients]. + * + * The maps will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. the maps' keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(denominatorCoefficients) + ) + +/** + * Constructs [LabeledRationalFunction] with provided [numerator] and unit denominator. + */ +public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one))) +/** + * Constructs [LabeledRationalFunction] with provided [numerator] and unit denominator. + */ +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, polynomialOne) + +/** + * Constructs [LabeledRationalFunction] with provided coefficients map [numeratorCoefficients] for numerator and unit + * denominator. + * + * [numeratorCoefficients] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [numeratorCoefficients]'s keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + polynomialOne + ) +/** + * Constructs [LabeledRationalFunction] with provided coefficients map [numeratorCoefficients] for numerator and unit + * denominator. + * + * [numeratorCoefficients] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [numeratorCoefficients]'s keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomialAsIs(mapOf(emptyMap() to one)) + ) + +///** +// * Converts [this] constant to [LabeledRationalFunction]. +// */ +//context(A) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = +// LabeledRationalFunction( +// LabeledPolynomialAsIs(mapOf(emptyMap() to this)), +// LabeledPolynomialAsIs(mapOf(emptyMap() to one)) +// ) +///** +// * Converts [this] constant to [LabeledRationalFunction]. +// */ +//context(LabeledRationalFunctionSpace) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = +// LabeledRationalFunction( +// LabeledPolynomialAsIs(mapOf(emptyMap() to this)), +// LabeledPolynomialAsIs(mapOf(emptyMap() to constantOne)) +// ) + +///** +// * Converts [this] variable to [LabeledRationalFunction]. +// */ +//context(A) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = +// LabeledRationalFunction( +// LabeledPolynomialAsIs(mapOf(mapOf(this to 1u) to one)), +// LabeledPolynomialAsIs(mapOf(emptyMap() to one)) +// ) +///** +// * Converts [this] variable to [LabeledRationalFunction]. +// */ +//context(LabeledRationalFunctionSpace) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = +// LabeledRationalFunction( +// LabeledPolynomialAsIs(mapOf(mapOf(this to 1u) to constantOne)), +// LabeledPolynomialAsIs(mapOf(emptyMap() to constantOne)) +// ) \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt new file mode 100644 index 000000000..188240bf7 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt @@ -0,0 +1,321 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName + + +/** + * Creates a [LabeledPolynomialSpace] over a received ring. + */ +public inline val > A.labeledPolynomialSpace: LabeledPolynomialSpace + get() = LabeledPolynomialSpace(this) + +/** + * Creates a [LabeledPolynomialSpace]'s scope over a received ring. + */ +public inline fun , R> A.labeledPolynomialSpace(block: LabeledPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return LabeledPolynomialSpace(this).block() +} +/** + * Creates a [LabeledRationalFunctionSpace] over a received ring. + */ +public inline val > A.labeledRationalFunctionSpace: LabeledRationalFunctionSpace + get() = LabeledRationalFunctionSpace(this) + +/** + * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. + */ +public inline fun , R> A.labeledRationalFunctionSpace(block: LabeledRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return LabeledRationalFunctionSpace(this).block() +} + +/** + * Substitutes provided Double arguments [args] into [this] Double polynomial. + */ +public fun LabeledPolynomial.substitute(args: Map): LabeledPolynomial = Double.algebra { + if (coefficients.isEmpty()) return this@substitute + LabeledPolynomial( + buildMap { + coefficients.forEach { (degs, c) -> + val newDegs = degs.filterKeys { it !in args } + val newC = args.entries.fold(c) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + putOrChange(newDegs, newC, ::add) + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ +public fun LabeledPolynomial.substitute(ring: Ring, args: Map): LabeledPolynomial = ring { + if (coefficients.isEmpty()) return this@substitute + LabeledPolynomial( + buildMap { + coefficients.forEach { (degs, c) -> + val newDegs = degs.filterKeys { it !in args } + val newC = args.entries.fold(c) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + putOrChange(newDegs, newC, ::add) + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substitutePolynomial") +public fun LabeledPolynomial.substitute(ring: Ring, args: Map>) : LabeledPolynomial = + ring.labeledPolynomialSpace { + coefficients.entries.fold(zero) { acc, (degs, c) -> + val newDegs = degs.filterKeys { it !in args } + acc + args.entries.fold(LabeledPolynomial(mapOf(newDegs to c))) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + } + } + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substituteRationalFunction") +public fun LabeledPolynomial.substitute(ring: Ring, args: Map>) : LabeledRationalFunction = + ring.labeledRationalFunctionSpace { + coefficients.entries.fold(zero) { acc, (degs, c) -> + val newDegs = degs.filterKeys { it !in args } + acc + args.entries.fold(LabeledRationalFunction(LabeledPolynomial(mapOf(newDegs to c)))) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + } + } + +/** + * Substitutes provided Double arguments [args] into [this] Double rational function. + */ +public fun LabeledRationalFunction.substitute(args: Map): LabeledRationalFunction = + LabeledRationalFunction(numerator.substitute(args), denominator.substitute(args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ +public fun LabeledRationalFunction.substitute(ring: Ring, args: Map): LabeledRationalFunction = + LabeledRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substitutePolynomial") +public fun LabeledRationalFunction.substitute(ring: Ring, args: Map>) : LabeledRationalFunction = + LabeledRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substituteRationalFunction") +public fun LabeledRationalFunction.substitute(ring: Ring, args: Map>) : LabeledRationalFunction = + ring.labeledRationalFunctionSpace { + numerator.substitute(ring, args) / denominator.substitute(ring, args) + } + +/** + * Returns algebraic derivative of received polynomial with respect to provided variable. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.derivativeWithRespectTo( + algebra: A, + variable: Symbol, +): LabeledPolynomial = algebra { + LabeledPolynomial( + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= 1u }) { + coefficients + .forEach { (degs, c) -> + if (variable !in degs) return@forEach + put( + buildMap { + degs.forEach { (vari, deg) -> + when { + vari != variable -> put(vari, deg) + deg > 1u -> put(vari, deg - 1u) + } + } + }, + multiplyByDoubling(c, degs[variable]!!) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variable of specified order. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthDerivativeWithRespectTo( + algebra: A, + variable: Symbol, + order: UInt +): LabeledPolynomial = algebra { + if (order == 0u) return this@nthDerivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= order }) { + coefficients + .forEach { (degs, c) -> + if (degs.getOrElse(variable) { 0u } < order) return@forEach + put( + buildMap { + degs.forEach { (vari, deg) -> + when { + vari != variable -> put(vari, deg) + deg > order -> put(vari, deg - order) + } + } + }, + degs[variable]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(c) { acc, ord -> multiplyByDoubling(acc, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variables of specified orders. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthDerivativeWithRespectTo( + algebra: A, + variablesAndOrders: Map, +): LabeledPolynomial = algebra { + val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } + if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo + LabeledPolynomial( + buildMap( + coefficients.count { + variablesAndOrders.all { (variable, order) -> + it.key.getOrElse(variable) { 0u } >= order + } + } + ) { + coefficients + .forEach { (degs, c) -> + if (filteredVariablesAndOrders.any { (variable, order) -> degs.getOrElse(variable) { 0u } < order }) return@forEach + put( + buildMap { + degs.forEach { (vari, deg) -> + if (vari !in filteredVariablesAndOrders) put(vari, deg) + else { + val order = filteredVariablesAndOrders[vari]!! + if (deg > order) put(vari, deg - order) + } + } + }, + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + degs[index]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> multiplyByDoubling(acc2, ord) } + } + } + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial with respect to provided variable. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.antiderivativeWithRespectTo( + algebra: A, + variable: Symbol, +): LabeledPolynomial = algebra { + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = degs.withPutOrChanged(variable, 1u) { it -> it + 1u } + put( + newDegs, + c / multiplyByDoubling(one, newDegs[variable]!!) + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial with respect to provided variable of specified order. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo( + algebra: A, + variable: Symbol, + order: UInt +): LabeledPolynomial = algebra { + if (order == 0u) return this@nthAntiderivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = degs.withPutOrChanged(variable, order) { it -> it + order } + put( + newDegs, + newDegs[variable]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variables of specified orders. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo( + algebra: A, + variablesAndOrders: Map, +): LabeledPolynomial = algebra { + val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } + if (filteredVariablesAndOrders.isEmpty()) return this@nthAntiderivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = mergeBy(degs, filteredVariablesAndOrders) { deg, order -> deg + order } + put( + newDegs, + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + newDegs[index]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> acc2 / multiplyByDoubling(one, ord) } + } + } + ) + } + } + ) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt new file mode 100644 index 000000000..30b1e2fe4 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.operations.Ring + + +/** + * Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(coefficients: List, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else this }) + +/** + * Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +/** + * Represents [this] constant as a [ListPolynomial]. + */ +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [ListRationalFunction] instance with numerator and denominator constructed with provided + * [numeratorCoefficients] and [denominatorCoefficients]. The both collections of coefficients will be reversed if + * [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) + ) +/** + * Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +/** + * Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +/** + * Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit + * denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) +/** + * Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit + * denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) + +/** + * Represents [this] constant as a rational function. + */ // FIXME: When context receivers will be ready, delete this function and uncomment the following two +public fun > C.asListRationalFunction(ring: A) : ListRationalFunction = ring.ListRationalFunction(asListPolynomial()) +///** +// * Represents [this] constant as a rational function. +// */ +//context(A) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) +///** +// * Represents [this] constant as a rational function. +// */ +//context(ListRationalFunctionSpace) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt new file mode 100644 index 000000000..e7c11f5ea --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -0,0 +1,255 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.math.max +import kotlin.math.pow + + +/** + * Creates a [ListPolynomialSpace] over a received ring. + */ +public inline val > A.listPolynomialSpace: ListPolynomialSpace + get() = ListPolynomialSpace(this) + +/** + * Creates a [ListPolynomialSpace]'s scope over a received ring. + */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] +public inline fun , R> A.listPolynomialSpace(block: ListPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ListPolynomialSpace(this).block() +} + +/** + * Creates a [ScalableListPolynomialSpace] over a received scalable ring. + */ +public inline val A.scalableListPolynomialSpace: ScalableListPolynomialSpace where A : Ring, A : ScaleOperations + get() = ScalableListPolynomialSpace(this) + +/** + * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. + */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] +public inline fun A.scalableListPolynomialSpace(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ScalableListPolynomialSpace(this).block() +} + +/** + * Creates a [ListRationalFunctionSpace] over a received ring. + */ +public inline val > A.listRationalFunctionSpace: ListRationalFunctionSpace + get() = ListRationalFunctionSpace(this) + +/** + * Creates a [ListRationalFunctionSpace]'s scope over a received ring. + */ // TODO: When context will be ready move [ListRationalFunctionSpace] and add [A] to context receivers of [block] +public inline fun , R> A.listRationalFunctionSpace(block: ListRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ListRationalFunctionSpace(this).block() +} + + +/** + * Evaluates value of [this] Double polynomial on provided Double argument. + */ +public fun ListPolynomial.substitute(arg: Double): Double = + coefficients.reduceIndexedOrNull { index, acc, c -> + acc + c * arg.pow(index) + } ?: .0 + +/** + * Evaluates value of [this] polynomial on provided argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun ListPolynomial.substitute(ring: Ring, arg: C): C = ring { + if (coefficients.isEmpty()) return zero + var result: C = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +/** + * Substitutes provided polynomial [arg] into [this] polynomial. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ // TODO: To optimize boxing +public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = + ring.listPolynomialSpace { + if (coefficients.isEmpty()) return zero + var result: ListPolynomial = coefficients.last().asPolynomial() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result + } + +/** + * Substitutes provided rational function [arg] into [this] polynomial. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ // TODO: To optimize boxing +public fun ListPolynomial.substitute(ring: Ring, arg: ListRationalFunction) : ListRationalFunction = + ring.listRationalFunctionSpace { + if (coefficients.isEmpty()) return zero + var result: ListRationalFunction = coefficients.last().asRationalFunction() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result + } + +/** + * Evaluates value of [this] Double rational function in provided Double argument. + */ +public fun ListRationalFunction.substitute(arg: Double): Double = + numerator.substitute(arg) / denominator.substitute(arg) + +/** + * Evaluates value of [this] polynomial for provided argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun ListRationalFunction.substitute(ring: Field, arg: C): C = ring { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) +} + +/** + * Substitutes provided polynomial [arg] into [this] rational function. + */ // TODO: To optimize boxing +public fun ListRationalFunction.substitute(ring: Ring, arg: ListPolynomial) : ListRationalFunction = + ring.listRationalFunctionSpace { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) + } + +/** + * Substitutes provided rational function [arg] into [this] rational function. + */ // TODO: To optimize boxing +public fun ListRationalFunction.substitute(ring: Ring, arg: ListRationalFunction) : ListRationalFunction = + ring.listRationalFunctionSpace { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) + } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfPolynomialOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfPolynomialOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun ListPolynomial.derivative( + ring: A, +): ListPolynomial where A : Ring, A : NumericAlgebra = ring { + ListPolynomial( + buildList(max(0, coefficients.size - 1)) { + for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) + } + ) +} + +/** + * Returns algebraic derivative of received polynomial of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public fun ListPolynomial.nthDerivative( + ring: A, + order: Int, +): ListPolynomial where A : Ring, A : NumericAlgebra = ring { + require(order >= 0) { "Order of derivative must be non-negative" } + ListPolynomial( + buildList(max(0, coefficients.size - order)) { + for (deg in order.. coefficients.lastIndex) + add((deg - order + 1 .. deg).fold(coefficients[deg]) { acc, d -> acc * number(d) }) + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun ListPolynomial.antiderivative( + ring: A, +): ListPolynomial where A : Field, A : NumericAlgebra = ring { + ListPolynomial( + buildList(coefficients.size + 1) { + add(zero) + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public fun ListPolynomial.nthAntiderivative( + ring: A, + order: Int, +): ListPolynomial where A : Field, A : NumericAlgebra = ring { + require(order >= 0) { "Order of antiderivative must be non-negative" } + ListPolynomial( + buildList(coefficients.size + order) { + repeat(order) { add(zero) } + coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } + } + ) +} + +/** + * Computes a definite integral of [this] polynomial in the specified [range]. + */ +@UnstableKMathAPI +public fun > ListPolynomial.integrate( + ring: Field, + range: ClosedRange, +): C = ring { + val antiderivative = antiderivative(ring) + antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt new file mode 100644 index 000000000..0a251b3b7 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2022 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.functions + + +/** + * Marks declarations that give access to internal entities of polynomials delicate structure. Thus, it allows to + * optimize performance a bit by skipping standard steps, but such skips may cause critical errors if something is + * implemented badly. Make sure you fully read and understand documentation and don't break internal contracts. + */ +@RequiresOptIn( + message = "This declaration gives access to delicate internal structure of polynomials. " + + "It allows to optimize performance by skipping unnecessary arguments check. " + + "But at the same time makes it easy to make a mistake " + + "that will cause wrong computation result or even runtime error. " + + "Make sure you fully read and understand documentation.", + level = RequiresOptIn.Level.ERROR +) +public annotation class DelicatePolynomialAPI \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt new file mode 100644 index 000000000..df4afbd12 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -0,0 +1,491 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("FunctionName", "NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Ring + + +/** + * Returns the same degrees' description of the monomial, but without extra zero degrees on the end. + */ +internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) + +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. The map is used as is. + */ +@PublishedApi +internal inline fun NumberedPolynomialAsIs(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) + +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * The collections will be transformed to map with [toMap] and then will be used as is. + */ +@PublishedApi +internal inline fun NumberedPolynomialAsIs(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) + +/** + * Constructs [NumberedPolynomial] with provided array of [pairs] of pairs "term's signature — term's coefficient". + * The array will be transformed to map with [toMap] and then will be used as is. + */ +@PublishedApi +internal inline fun NumberedPolynomialAsIs(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) + +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. The map is used as is. + * + * **Be sure you read description of [NumberedPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun NumberedPolynomialWithoutCheck(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) + +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * The collections will be transformed to map with [toMap] and then will be used as is. + * + * **Be sure you read description of [NumberedPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun NumberedPolynomialWithoutCheck(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) + +/** + * Constructs [NumberedPolynomial] with provided array of [pairs] of pairs "term's signature — term's coefficient". + * The array will be transformed to map with [toMap] and then will be used as is. + * + * **Be sure you read description of [NumberedPolynomial.coefficients]. Otherwise, you may make a mistake that will + * cause wrong computation result or even runtime error.** + */ +@DelicatePolynomialAPI +public inline fun NumberedPolynomialWithoutCheck(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) + +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public fun NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : NumberedPolynomial = + NumberedPolynomialAsIs( + coefs.mapKeys({ key, _ -> key.cleanUp() }, add) + ) + +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public fun NumberedPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : NumberedPolynomial = + NumberedPolynomialAsIs( + pairs.associateBy({ it.first.cleanUp() }, { it.second }, add) + ) + +/** + * Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : NumberedPolynomial = + NumberedPolynomialAsIs( + pairs.asIterable().associateBy({ it.first.cleanUp() }, { it.second }, add) + ) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, ::add) +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) { left: C, right: C -> left + right } + +/** + * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. + * + * [coefs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [coefs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) { left: C, right: C -> left + right } + +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, ::add) + +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs) { left: C, right: C -> left + right } +/** + * Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs) { left: C, right: C -> left + right } + +/** + * Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } +/** + * Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } +/** + * Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient". + * + * [pairs] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [pairs] keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + * + * @see NumberedPolynomialWithoutCheck + */ +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } + +/** + * Converts [this] constant to [NumberedPolynomial]. + */ +public inline fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomialAsIs(mapOf(emptyList() to this)) + +/** + * Marks DSL that allows to more simply create [NumberedPolynomial]s with good performance. + * + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + + * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 + * } + * } + * ``` + * @usesMathJax + */ +@DslMarker +@UnstableKMathAPI +internal annotation class NumberedPolynomialConstructorDSL1 + +/** + * Builder of [NumberedPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. + */ +@UnstableKMathAPI +@NumberedPolynomialConstructorDSL1 +public class DSL1NumberedPolynomialTermSignatureBuilder { + /** + * Signature storage. Any declaration of any variable's power updates the storage by increasing corresponding value. + * Afterward the storage will be used as a resulting signature. + */ + private val signature: MutableList = ArrayList() + + /** + * Builds the resulting signature. + * + * In fact, it just returns [signature] as regular signature of type `List`. + */ + @PublishedApi + internal fun build(): List = signature + + /** + * Declares power of variable #[this] of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public infix fun Int.inPowerOf(deg: UInt) { + if (deg == 0u) return + val index = this + if (index > signature.lastIndex) { + signature.addAll(List(index - signature.lastIndex - 1) { 0u }) + signature.add(deg) + } else { + signature[index] += deg + } + } + /** + * Declares power of variable #[this] of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg + /** + * Declares power of variable #[this] of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Int.`in`(deg: UInt): Unit = this inPowerOf deg + /** + * Declares power of variable #[this] of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg +} + +/** + * Builder of [NumberedPolynomial]. It should be used as an implicit context for lambdas that describe [NumberedPolynomial]. + */ +@UnstableKMathAPI +@NumberedPolynomialConstructorDSL1 +public class DSL1NumberedPolynomialBuilder( + /** + * Summation operation that will be used to sum coefficients of monomials of same signatures. + */ + private val add: (C, C) -> C, + /** + * Initial capacity of coefficients map. + */ + initialCapacity: Int? = null +) { + /** + * Coefficients storage. Any declaration of any monomial updates the storage. + * Afterward the storage will be used as a resulting coefficients map. + */ + private val coefficients: MutableMap, C> = if (initialCapacity != null) LinkedHashMap(initialCapacity) else LinkedHashMap() + + /** + * Builds the resulting coefficients map. + * + * In fact, it just returns [coefficients] as regular coefficients map of type `Map, C>`. + */ + @PublishedApi + internal fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + + /** + * Declares monomial with [this] coefficient and provided [signature]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public infix fun C.with(signature: List) { + coefficients.putOrChange(signature, this@with, add) + } + /** + * Declares monomial with [this] coefficient and signature constructed by [block]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public inline infix fun C.with(noinline block: DSL1NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + /** + * Declares monomial with [this] coefficient and signature constructed by [block]. + * + * Declaring another monomial with the same signature will add [this] coefficient to existing one. If the sum of such + * coefficients is zero at any moment the monomial won't be removed but will be left as it is. + */ + public inline operator fun C.invoke(block: DSL1NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = + this with DSL1NumberedPolynomialTermSignatureBuilder().apply(block).build() +} + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +///** +// * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of constants. +// * +// * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as +// * ``` +// * Int.algebra { +// * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { +// * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + +// * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 +// * } +// * } +// * ``` +// * @usesMathJax +// */ +// FIXME: For now this fabric does not let next two fabrics work. (See KT-52803.) Possible feature solutions: +// 1. `LowPriorityInOverloadResolution` becomes public. Then it should be applied to this function. +// 2. Union types are implemented. Then all three functions should be rewritten +// as one with single union type as a (context) receiver. +//@UnstableKMathAPI +//public inline fun > A.NumberedPolynomialDSL1(initialCapacity: Int? = null, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() +/** + * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. + * + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + + * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 + * } + * } + * ``` + * @usesMathJax + */ +@UnstableKMathAPI +public inline fun > NumberedPolynomialSpace.NumberedPolynomialDSL1(initialCapacity: Int? = null, block: DSL1NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = DSL1NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +/** + * Creates [NumberedPolynomial] with lambda [block] in context of [this] field of [NumberedRationalFunction]s. + * + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + + * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 + * } + * } + * ``` + * @usesMathJax + */ +@UnstableKMathAPI +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomialDSL1(initialCapacity: Int? = null, block: DSL1NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = DSL1NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [NumberedRationalFunction] with provided coefficients maps [numeratorCoefficients] and [denominatorCoefficients]. + * + * The maps will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. the maps' keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(denominatorCoefficients) + ) +/** + * Constructs [NumberedRationalFunction] with provided coefficients maps [numeratorCoefficients] and [denominatorCoefficients]. + * + * The maps will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. the maps' keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(denominatorCoefficients) + ) + +/** + * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. + */ +public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) +/** + * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. + */ +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, polynomialOne) + +/** + * Constructs [NumberedRationalFunction] with provided coefficients map [numeratorCoefficients] for numerator and unit + * denominator. + * + * [numeratorCoefficients] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [numeratorCoefficients]'s keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + polynomialOne + ) +/** + * Constructs [NumberedRationalFunction] with provided coefficients map [numeratorCoefficients] for numerator and unit + * denominator. + * + * [numeratorCoefficients] will be "cleaned up": + * 1. Zeros at the ends of terms' signatures (e.g. [numeratorCoefficients]'s keys) will be removed. (See [cleanUp].) + * 1. Terms that happen to have the same signature will be summed up. + * 1. New map will be formed of resulting terms. + */ +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomialAsIs(mapOf(emptyList() to one)) + ) + +///** +// * Converts [this] constant to [NumberedRationalFunction]. +// */ +//context(A) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = +// NumberedRationalFunction( +// NumberedPolynomialAsIs(mapOf(emptyList() to this)), +// NumberedPolynomialAsIs(mapOf(emptyList() to one)) +// ) +///** +// * Converts [this] constant to [NumberedRationalFunction]. +// */ +//context(NumberedRationalFunctionSpace) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = +// NumberedRationalFunction( +// NumberedPolynomialAsIs(mapOf(emptyList() to this)), +// NumberedPolynomialAsIs(mapOf(emptyList() to constantOne)) +// ) \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt new file mode 100644 index 000000000..88424d23c --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -0,0 +1,513 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName +import kotlin.math.max +import kotlin.math.min + + +/** + * Creates a [NumberedPolynomialSpace] over a received ring. + */ +public inline val > A.numberedPolynomialSpace: NumberedPolynomialSpace + get() = NumberedPolynomialSpace(this) + +/** + * Creates a [NumberedPolynomialSpace]'s scope over a received ring. + */ +public inline fun , R> A.numberedPolynomialSpace(block: NumberedPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return NumberedPolynomialSpace(this).block() +} + +/** + * Creates a [NumberedRationalFunctionSpace] over a received ring. + */ +public inline val > A.numberedRationalFunctionSpace: NumberedRationalFunctionSpace + get() = NumberedRationalFunctionSpace(this) + +/** + * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. + */ +public inline fun , R> A.numberedRationalFunctionSpace(block: NumberedRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return NumberedRationalFunctionSpace(this).block() +} + +/** + * Substitutes provided Double arguments [args] into [this] Double polynomial. + */ +public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + for ((degs, c) in coefficients) { + val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp() + val newC = args.entries.fold(c) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * substitution.pow(deg.toInt()) + } + putOrChange(newDegs, newC) { it -> it + newC } + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ +public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { + NumberedPolynomial( + buildMap(coefficients.size) { + for ((degs, c) in coefficients) { + val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp() + val newC = args.entries.fold(c) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + putOrChange(newDegs, newC) { it -> it + newC } + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substitutePolynomial") +public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = + ring.numberedPolynomialSpace { + coefficients.entries.fold(zero) { acc, (degs, c) -> + val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp() + acc + args.entries.fold(NumberedPolynomial(mapOf(newDegs to c))) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + } + } + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substituteRationalFunction") +public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedRationalFunction = + ring.numberedRationalFunctionSpace { + coefficients.entries.fold(zero) { acc, (degs, c) -> + val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp() + acc + args.entries.fold(NumberedRationalFunction(NumberedPolynomial(mapOf(newDegs to c)))) { product, (variable, substitution) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitution, deg) + } + } + } + +/** + * Substitutes provided Double arguments [args] into [this] Double rational function. + */ +public fun NumberedRationalFunction.substitute(args: Map): NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(args), denominator.substitute(args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ +public fun NumberedRationalFunction.substitute(ring: Ring, args: Map): NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substitutePolynomial") +public fun NumberedRationalFunction.substitute(ring: Ring, args: Map>) : NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substituteRationalFunction") +public fun NumberedRationalFunction.substitute(ring: Ring, args: Map>) : NumberedRationalFunction = + ring.numberedRationalFunctionSpace { + numerator.substitute(ring, args) / denominator.substitute(ring, args) + } + +/** + * Substitutes provided Double arguments [args] into [this] Double polynomial. + */ +public fun NumberedPolynomial.substitute(args: Buffer): NumberedPolynomial = Double.algebra { + val lastSubstitutionVariable = args.size - 1 + NumberedPolynomial( + buildMap(coefficients.size) { + for ((degs, c) in coefficients) { + val lastDegsIndex = degs.lastIndex + val newDegs = + if (lastDegsIndex <= lastSubstitutionVariable) emptyList() + else degs.toMutableList().apply { + for (i in 0..lastSubstitutionVariable) this[i] = 0u + } + val newC = (0..min(lastDegsIndex, lastSubstitutionVariable)).fold(c) { product, variable -> + val deg = degs[variable] + if (deg == 0u) product else product * args[variable].pow(deg.toInt()) + } + putOrChange(newDegs, newC) { it -> it + newC } + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ +public fun NumberedPolynomial.substitute(ring: Ring, args: Buffer): NumberedPolynomial = ring { + val lastSubstitutionVariable = args.size - 1 + NumberedPolynomial( + buildMap, C>(coefficients.size) { + for ((degs, c) in coefficients) { + val lastDegsIndex = degs.lastIndex + val newDegs = + if (lastDegsIndex <= lastSubstitutionVariable) emptyList() + else degs.toMutableList().apply { + for (i in 0..lastSubstitutionVariable) this[i] = 0u + } + val newC = (0..min(lastDegsIndex, lastSubstitutionVariable)).fold(c) { product, variable -> + val deg = degs[variable] + if (deg == 0u) product else product * power(args[variable], deg) + } + putOrChange(newDegs, newC) { it -> it + newC } + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substitutePolynomial") +public fun NumberedPolynomial.substitute(ring: Ring, args: Buffer>) : NumberedPolynomial = + ring.numberedPolynomialSpace { + val lastSubstitutionVariable = args.size - 1 + coefficients.entries.fold(zero) { acc, (degs, c) -> + val lastDegsIndex = degs.lastIndex + val newDegs = + if (lastDegsIndex <= lastSubstitutionVariable) emptyList() + else degs.toMutableList().apply { + for (i in 0..lastSubstitutionVariable) this[i] = 0u + } + acc + (0..min(lastDegsIndex, lastSubstitutionVariable)) + .fold(NumberedPolynomial(mapOf(newDegs to c))) { product, variable -> + val deg = degs[variable] + if (deg == 0u) product else product * power(args[variable], deg) + } + } + } + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ // TODO: To optimize boxing +@JvmName("substituteRationalFunction") +public fun NumberedPolynomial.substitute(ring: Ring, args: Buffer>) : NumberedRationalFunction = + ring.numberedRationalFunctionSpace { + val lastSubstitutionVariable = args.size - 1 + coefficients.entries.fold(zero) { acc, (degs, c) -> + val lastDegsIndex = degs.lastIndex + val newDegs = + if (lastDegsIndex <= lastSubstitutionVariable) emptyList() + else degs.toMutableList().apply { + for (i in 0..lastSubstitutionVariable) this[i] = 0u + } + acc + (0..min(lastDegsIndex, lastSubstitutionVariable)) + .fold(NumberedRationalFunction(NumberedPolynomial(mapOf(newDegs to c)))) { product, variable -> + val deg = degs[variable] + if (deg == 0u) product else product * power(args[variable], deg) + } + } + } + +/** + * Substitutes provided Double arguments [args] into [this] Double rational function. + */ +public fun NumberedRationalFunction.substitute(args: Buffer): NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(args), denominator.substitute(args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ +public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffer): NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substitutePolynomial") +public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffer>) : NumberedRationalFunction = + NumberedRationalFunction(numerator.substitute(ring, args), denominator.substitute(ring, args)) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ // TODO: To optimize calculation +@JvmName("substituteRationalFunction") +public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffer>) : NumberedRationalFunction = + ring.numberedRationalFunctionSpace { + numerator.substitute(ring, args) / denominator.substitute(ring, args) + } + +internal const val fullSubstitutionExceptionMessage: String = "Fully substituting buffer should cover all variables of the polynomial." + +/** + * Substitutes provided Double arguments [args] into [this] Double polynomial. + */ +public fun NumberedPolynomial.substituteFully(args: Buffer): Double = Double.algebra { + val lastSubstitutionVariable = args.size - 1 + require(coefficients.keys.all { it.lastIndex <= lastSubstitutionVariable }) { fullSubstitutionExceptionMessage } + coefficients.entries.fold(.0) { acc, (degs, c) -> + acc + degs.foldIndexed(c) { variable, product, deg -> + if (deg == 0u) product else product * args[variable].pow(deg.toInt()) + } + } +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ +public fun NumberedPolynomial.substituteFully(ring: Ring, args: Buffer): C = ring { + val lastSubstitutionVariable = args.size - 1 + require(coefficients.keys.all { it.lastIndex <= lastSubstitutionVariable }) { fullSubstitutionExceptionMessage } + coefficients.entries.fold(zero) { acc, (degs, c) -> + acc + degs.foldIndexed(c) { variable, product, deg -> + if (deg == 0u) product else product * power(args[variable], deg) + } + } +} + +/** + * Substitutes provided Double arguments [args] into [this] Double rational function. + */ +public fun NumberedRationalFunction.substituteFully(args: Buffer): Double = + numerator.substituteFully(args) / denominator.substituteFully(args) + +/** + * Substitutes provided arguments [args] into [this] rational function. + */ +public fun NumberedRationalFunction.substituteFully(ring: Field, args: Buffer): C = ring { + numerator.substituteFully(ring, args) / denominator.substituteFully(ring, args) +} + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunctionOver(ring: A): (Buffer) -> C = { substituteFully(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunctionOfConstantOver(ring: A): (Buffer) -> C = { substituteFully(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunctionOfPolynomialOver(ring: A): (Buffer>) -> NumberedPolynomial = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunctionOfRationalFunctionOver(ring: A): (Buffer>) -> NumberedRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > NumberedRationalFunction.asFunctionOver(ring: A): (Buffer) -> C = { substituteFully(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > NumberedRationalFunction.asFunctionOfConstantOver(ring: A): (Buffer) -> C = { substituteFully(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > NumberedRationalFunction.asFunctionOfPolynomialOver(ring: A): (Buffer>) -> NumberedRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > NumberedRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (Buffer>) -> NumberedRationalFunction = { substitute(ring, it) } + +/** + * Returns algebraic derivative of received polynomial with respect to provided variable. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.derivativeWithRespectTo( + ring: A, + variable: Int, +): NumberedPolynomial = ring { + NumberedPolynomial( + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= 1u }) { + coefficients + .forEach { (degs, c) -> + if (degs.lastIndex < variable) return@forEach + put( + degs.mapIndexed { index, deg -> + when { + index != variable -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }.cleanUp(), + multiplyByDoubling(c, degs[variable]) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variable of specified order. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthDerivativeWithRespectTo( + ring: A, + variable: Int, + order: UInt +): NumberedPolynomial = ring { + if (order == 0u) return this@nthDerivativeWithRespectTo + NumberedPolynomial( + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= order }) { + coefficients + .forEach { (degs, c) -> + if (degs.lastIndex < variable) return@forEach + put( + degs.mapIndexed { index, deg -> + when { + index != variable -> deg + deg >= order -> deg - order + else -> return@forEach + } + }.cleanUp(), + degs[variable].let { deg -> + (deg downTo deg - order + 1u) + .fold(c) { acc, ord -> multiplyByDoubling(acc, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variables of specified orders. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthDerivativeWithRespectTo( + ring: A, + variablesAndOrders: Map, +): NumberedPolynomial = ring { + val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } + if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo + val maxRespectedVariable = filteredVariablesAndOrders.keys.maxOrNull()!! + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + if (degs.lastIndex < maxRespectedVariable) return@forEach + put( + degs.mapIndexed { index, deg -> + if (index !in filteredVariablesAndOrders) return@mapIndexed deg + val order = filteredVariablesAndOrders[index]!! + if (deg >= order) deg - order else return@forEach + }.cleanUp(), + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + degs[index].let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> multiplyByDoubling(acc2, ord) } + } + } + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial with respect to provided variable. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.antiderivativeWithRespectTo( + ring: A, + variable: Int, +): NumberedPolynomial = ring { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + put( + List(max(variable + 1, degs.size)) { degs.getOrElse(it) { 0u } + if (it != variable) 0u else 1u }, + c / multiplyByDoubling(one, degs.getOrElse(variable) { 0u } + 1u) + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial with respect to provided variable of specified order. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( + ring: A, + variable: Int, + order: UInt +): NumberedPolynomial = ring { + if (order == 0u) return this@nthAntiderivativeWithRespectTo + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + put( + List(max(variable + 1, degs.size)) { degs.getOrElse(it) { 0u } + if (it != variable) 0u else order }, + degs.getOrElse(variable) { 0u }.let { deg -> + (deg + 1u .. deg + order) + .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial with respect to provided variables of specified orders. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( + ring: A, + variablesAndOrders: Map, +): NumberedPolynomial = ring { + val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } + if (filteredVariablesAndOrders.isEmpty()) return this@nthAntiderivativeWithRespectTo + val maxRespectedVariable = filteredVariablesAndOrders.keys.maxOrNull()!! + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + put( + List(max(maxRespectedVariable + 1, degs.size)) { degs.getOrElse(it) { 0u } + filteredVariablesAndOrders.getOrElse(it) { 0u } }, + filteredVariablesAndOrders.entries.fold(c) { acc1, (variable, order) -> + degs.getOrElse(variable) { 0u }.let { deg -> + (deg + 1u .. deg + order) + .fold(acc1) { acc, ord -> acc / multiplyByDoubling(one, ord) } + } + } + ) + } + } + ) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt new file mode 100644 index 000000000..9dd2bb743 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -0,0 +1,589 @@ +/* + * Copyright 2018-2022 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.functions + + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.Field +import kotlin.jvm.JvmInline +import kotlin.test.Test +import kotlin.test.assertEquals + +@JvmInline +value class Expr(val expr: String) + +object ExprRing : Field { + override fun Expr.unaryMinus(): Expr = Expr("-${expr}") + override fun add(left: Expr, right: Expr): Expr = Expr("(${left.expr} + ${right.expr})") + override fun multiply(left: Expr, right: Expr): Expr = Expr("(${left.expr} * ${right.expr})") + override val zero: Expr = Expr("0") + override val one: Expr = Expr("1") + override fun divide(left: Expr, right: Expr): Expr = Expr("(${left.expr} / ${right.expr})") + override fun scale(a: Expr, value: Double): Expr = Expr("(${a.expr} / $value)") +} + +class AlgebraicStubTest { + @Test + fun test_addMultipliedBySquaring_for_UInt() { + ExprRing { + assertEquals( + "57", + addMultipliedByDoubling(Expr("57"), Expr("179"), 0u).expr, + "tried addMultipliedBySquaring(57, 179, 0u)" + ) + assertEquals( + "(57 + 179)", + addMultipliedByDoubling(Expr("57"), Expr("179"), 1u).expr, + "tried addMultipliedBySquaring(57, 179, 1u)" + ) + assertEquals( + "(57 + (179 + 179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 2u).expr, + "tried addMultipliedBySquaring(57, 179, 2u)" + ) + assertEquals( + "((57 + 179) + (179 + 179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 3u).expr, + "tried addMultipliedBySquaring(57, 179, 3u)" + ) + assertEquals( + "(57 + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 4u).expr, + "tried addMultipliedBySquaring(57, 179, 4u)" + ) + assertEquals( + "((57 + 179) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 5u).expr, + "tried addMultipliedBySquaring(57, 179, 5u)" + ) + assertEquals( + "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 6u).expr, + "tried addMultipliedBySquaring(57, 179, 6u)" + ) + assertEquals( + "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 7u).expr, + "tried addMultipliedBySquaring(57, 179, 7u)" + ) + assertEquals( + "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 8u).expr, + "tried addMultipliedBySquaring(57, 179, 8u)" + ) + } + } + @Test + fun test_multiplyBySquaring_for_UInt() { + ExprRing { + assertEquals( + "0", + multiplyByDoubling(Expr("57"), 0u).expr, + "tried multiplyBySquaring(57, 0u)" + ) + assertEquals( + "57", + multiplyByDoubling(Expr("57"), 1u).expr, + "tried multiplyBySquaring(57, 1u)" + ) + assertEquals( + "(57 + 57)", + multiplyByDoubling(Expr("57"), 2u).expr, + "tried multiplyBySquaring(57, 2u)" + ) + assertEquals( + "(57 + (57 + 57))", + multiplyByDoubling(Expr("57"), 3u).expr, + "tried multiplyBySquaring(57, 3u)" + ) + assertEquals( + "((57 + 57) + (57 + 57))", + multiplyByDoubling(Expr("57"), 4u).expr, + "tried multiplyBySquaring(57, 4u)" + ) + assertEquals( + "(57 + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 5u).expr, + "tried multiplyBySquaring(57, 5u)" + ) + assertEquals( + "((57 + 57) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 6u).expr, + "tried multiplyBySquaring(57, 6u)" + ) + assertEquals( + "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 7u).expr, + "tried multiplyBySquaring(57, 7u)" + ) + assertEquals( + "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 8u).expr, + "tried multiplyBySquaring(57, 8u)" + ) + } + } + @Test + fun test_addMultipliedBySquaring_for_Int() { + ExprRing { + assertEquals( + "57", + addMultipliedByDoubling(Expr("57"), Expr("179"), 0).expr, + "tried addMultipliedBySquaring(57, 179, 0)" + ) + assertEquals( + "(57 + 179)", + addMultipliedByDoubling(Expr("57"), Expr("179"), 1).expr, + "tried addMultipliedBySquaring(57, 179, 1)" + ) + assertEquals( + "(57 + -179)", + addMultipliedByDoubling(Expr("57"), Expr("179"), -1).expr, + "tried addMultipliedBySquaring(57, 179, -1)" + ) + assertEquals( + "(57 + (179 + 179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 2).expr, + "tried addMultipliedBySquaring(57, 179, 2)" + ) + assertEquals( + "(57 + (-179 + -179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -2).expr, + "tried addMultipliedBySquaring(57, 179, -2)" + ) + assertEquals( + "((57 + 179) + (179 + 179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 3).expr, + "tried addMultipliedBySquaring(57, 179, 3)" + ) + assertEquals( + "((57 + -179) + (-179 + -179))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -3).expr, + "tried addMultipliedBySquaring(57, 179, -3)" + ) + assertEquals( + "(57 + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 4).expr, + "tried addMultipliedBySquaring(57, 179, 4)" + ) + assertEquals( + "(57 + ((-179 + -179) + (-179 + -179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -4).expr, + "tried addMultipliedBySquaring(57, 179, -4)" + ) + assertEquals( + "((57 + 179) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 5).expr, + "tried addMultipliedBySquaring(57, 179, 5)" + ) + assertEquals( + "((57 + -179) + ((-179 + -179) + (-179 + -179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -5).expr, + "tried addMultipliedBySquaring(57, 179, -5)" + ) + assertEquals( + "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 6).expr, + "tried addMultipliedBySquaring(57, 179, 6)" + ) + assertEquals( + "((57 + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -6).expr, + "tried addMultipliedBySquaring(57, 179, -6)" + ) + assertEquals( + "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 7).expr, + "tried addMultipliedBySquaring(57, 179, 7)" + ) + assertEquals( + "(((57 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -7).expr, + "tried addMultipliedBySquaring(57, 179, -7)" + ) + assertEquals( + "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", + addMultipliedByDoubling(Expr("57"), Expr("179"), 8).expr, + "tried addMultipliedBySquaring(57, 179, 8)" + ) + assertEquals( + "(57 + (((-179 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179))))", + addMultipliedByDoubling(Expr("57"), Expr("179"), -8).expr, + "tried addMultipliedBySquaring(57, 179, -8)" + ) + } + } + @Test + fun test_multiplyBySquaring_for_Int() { + ExprRing { + assertEquals( + "0", + multiplyByDoubling(Expr("57"), 0).expr, + "tried multiplyBySquaring(57, 0)" + ) + assertEquals( + "57", + multiplyByDoubling(Expr("57"), 1).expr, + "tried multiplyBySquaring(57, 1)" + ) + assertEquals( + "-57", + multiplyByDoubling(Expr("57"), -1).expr, + "tried multiplyBySquaring(57, -1)" + ) + assertEquals( + "(57 + 57)", + multiplyByDoubling(Expr("57"), 2).expr, + "tried multiplyBySquaring(57, 2)" + ) + assertEquals( + "(-57 + -57)", + multiplyByDoubling(Expr("57"), -2).expr, + "tried multiplyBySquaring(57, -2)" + ) + assertEquals( + "(57 + (57 + 57))", + multiplyByDoubling(Expr("57"), 3).expr, + "tried multiplyBySquaring(57, 3)" + ) + assertEquals( + "(-57 + (-57 + -57))", + multiplyByDoubling(Expr("57"), -3).expr, + "tried multiplyBySquaring(57, -3)" + ) + assertEquals( + "((57 + 57) + (57 + 57))", + multiplyByDoubling(Expr("57"), 4).expr, + "tried multiplyBySquaring(57, 4)" + ) + assertEquals( + "((-57 + -57) + (-57 + -57))", + multiplyByDoubling(Expr("57"), -4).expr, + "tried multiplyBySquaring(57, -4)" + ) + assertEquals( + "(57 + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 5).expr, + "tried multiplyBySquaring(57, 5)" + ) + assertEquals( + "(-57 + ((-57 + -57) + (-57 + -57)))", + multiplyByDoubling(Expr("57"), -5).expr, + "tried multiplyBySquaring(57, -5)" + ) + assertEquals( + "((57 + 57) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 6).expr, + "tried multiplyBySquaring(57, 6)" + ) + assertEquals( + "((-57 + -57) + ((-57 + -57) + (-57 + -57)))", + multiplyByDoubling(Expr("57"), -6).expr, + "tried multiplyBySquaring(57, -6)" + ) + assertEquals( + "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 7).expr, + "tried multiplyBySquaring(57, 7)" + ) + assertEquals( + "((-57 + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", + multiplyByDoubling(Expr("57"), -7).expr, + "tried multiplyBySquaring(57, -7)" + ) + assertEquals( + "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyByDoubling(Expr("57"), 8).expr, + "tried multiplyBySquaring(57, 8)" + ) + assertEquals( + "(((-57 + -57) + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", + multiplyByDoubling(Expr("57"), -8).expr, + "tried multiplyBySquaring(57, -8)" + ) + } + } + @Test + fun test_multiplyExponentiationBySquaring_for_UInt() { + ExprRing { + assertEquals( + "57", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 0u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 0u)" + ) + assertEquals( + "(57 * 179)", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 1u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 1u)" + ) + assertEquals( + "(57 * (179 * 179))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 2u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 2u)" + ) + assertEquals( + "((57 * 179) * (179 * 179))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 3u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 3u)" + ) + assertEquals( + "(57 * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 4u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 4u)" + ) + assertEquals( + "((57 * 179) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 5u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 5u)" + ) + assertEquals( + "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 6u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 6u)" + ) + assertEquals( + "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 7u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 7u)" + ) + assertEquals( + "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 8u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 8u)" + ) + } + } + @Test + fun test_exponentiationBySquaring_for_UInt() { + ExprRing { + assertEquals( + "0", + exponentiateBySquaring(Expr("57"), 0u).expr, + "tried exponentiationBySquaring(57, 0u)" + ) + assertEquals( + "57", + exponentiateBySquaring(Expr("57"), 1u).expr, + "tried exponentiationBySquaring(57, 1u)" + ) + assertEquals( + "(57 * 57)", + exponentiateBySquaring(Expr("57"), 2u).expr, + "tried exponentiationBySquaring(57, 2u)" + ) + assertEquals( + "(57 * (57 * 57))", + exponentiateBySquaring(Expr("57"), 3u).expr, + "tried exponentiationBySquaring(57, 3u)" + ) + assertEquals( + "((57 * 57) * (57 * 57))", + exponentiateBySquaring(Expr("57"), 4u).expr, + "tried exponentiationBySquaring(57, 4u)" + ) + assertEquals( + "(57 * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 5u).expr, + "tried exponentiationBySquaring(57, 5u)" + ) + assertEquals( + "((57 * 57) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 6u).expr, + "tried exponentiationBySquaring(57, 6u)" + ) + assertEquals( + "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 7u).expr, + "tried exponentiationBySquaring(57, 7u)" + ) + assertEquals( + "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 8u).expr, + "tried exponentiationBySquaring(57, 8u)" + ) + } + } + @Test + fun test_multiplyExponentiationBySquaring_for_Int() { + ExprRing { + assertEquals( + "57", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 0).expr, + "tried multiplyExponentiationBySquaring(57, 179, 0)" + ) + assertEquals( + "(57 * 179)", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 1).expr, + "tried multiplyExponentiationBySquaring(57, 179, 1)" + ) + assertEquals( + "(57 * (1 / 179))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -1).expr, + "tried multiplyExponentiationBySquaring(57, 179, -1)" + ) + assertEquals( + "(57 * (179 * 179))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 2).expr, + "tried multiplyExponentiationBySquaring(57, 179, 2)" + ) + assertEquals( + "(57 * ((1 / 179) * (1 / 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -2).expr, + "tried multiplyExponentiationBySquaring(57, 179, -2)" + ) + assertEquals( + "((57 * 179) * (179 * 179))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 3).expr, + "tried multiplyExponentiationBySquaring(57, 179, 3)" + ) + assertEquals( + "((57 * (1 / 179)) * ((1 / 179) * (1 / 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -3).expr, + "tried multiplyExponentiationBySquaring(57, 179, -3)" + ) + assertEquals( + "(57 * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 4).expr, + "tried multiplyExponentiationBySquaring(57, 179, 4)" + ) + assertEquals( + "(57 * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -4).expr, + "tried multiplyExponentiationBySquaring(57, 179, -4)" + ) + assertEquals( + "((57 * 179) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 5).expr, + "tried multiplyExponentiationBySquaring(57, 179, 5)" + ) + assertEquals( + "((57 * (1 / 179)) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -5).expr, + "tried multiplyExponentiationBySquaring(57, 179, -5)" + ) + assertEquals( + "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 6).expr, + "tried multiplyExponentiationBySquaring(57, 179, 6)" + ) + assertEquals( + "((57 * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -6).expr, + "tried multiplyExponentiationBySquaring(57, 179, -6)" + ) + assertEquals( + "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 7).expr, + "tried multiplyExponentiationBySquaring(57, 179, 7)" + ) + assertEquals( + "(((57 * (1 / 179)) * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -7).expr, + "tried multiplyExponentiationBySquaring(57, 179, -7)" + ) + assertEquals( + "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 8).expr, + "tried multiplyExponentiationBySquaring(57, 179, 8)" + ) + assertEquals( + "(57 * ((((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179)))))", + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -8).expr, + "tried multiplyExponentiationBySquaring(57, 179, -8)" + ) + } + } + @Test + fun test_exponentiationBySquaring_for_Int() { + ExprRing { + assertEquals( + "0", + exponentiateBySquaring(Expr("57"), 0).expr, + "tried exponentiationBySquaring(57, 0)" + ) + assertEquals( + "57", + exponentiateBySquaring(Expr("57"), 1).expr, + "tried exponentiationBySquaring(57, 1)" + ) + assertEquals( + "(1 / 57)", + exponentiateBySquaring(Expr("57"), -1).expr, + "tried exponentiationBySquaring(57, -1)" + ) + assertEquals( + "(57 * 57)", + exponentiateBySquaring(Expr("57"), 2).expr, + "tried exponentiationBySquaring(57, 2)" + ) + assertEquals( + "((1 / 57) * (1 / 57))", + exponentiateBySquaring(Expr("57"), -2).expr, + "tried exponentiationBySquaring(57, -2)" + ) + assertEquals( + "(57 * (57 * 57))", + exponentiateBySquaring(Expr("57"), 3).expr, + "tried exponentiationBySquaring(57, 3)" + ) + assertEquals( + "((1 / 57) * ((1 / 57) * (1 / 57)))", + exponentiateBySquaring(Expr("57"), -3).expr, + "tried exponentiationBySquaring(57, -3)" + ) + assertEquals( + "((57 * 57) * (57 * 57))", + exponentiateBySquaring(Expr("57"), 4).expr, + "tried exponentiationBySquaring(57, 4)" + ) + assertEquals( + "(((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57)))", + exponentiateBySquaring(Expr("57"), -4).expr, + "tried exponentiationBySquaring(57, -4)" + ) + assertEquals( + "(57 * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 5).expr, + "tried exponentiationBySquaring(57, 5)" + ) + assertEquals( + "((1 / 57) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiateBySquaring(Expr("57"), -5).expr, + "tried exponentiationBySquaring(57, -5)" + ) + assertEquals( + "((57 * 57) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 6).expr, + "tried exponentiationBySquaring(57, 6)" + ) + assertEquals( + "(((1 / 57) * (1 / 57)) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiateBySquaring(Expr("57"), -6).expr, + "tried exponentiationBySquaring(57, -6)" + ) + assertEquals( + "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 7).expr, + "tried exponentiationBySquaring(57, 7)" + ) + assertEquals( + "(((1 / 57) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiateBySquaring(Expr("57"), -7).expr, + "tried exponentiationBySquaring(57, -7)" + ) + assertEquals( + "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiateBySquaring(Expr("57"), 8).expr, + "tried exponentiationBySquaring(57, 8)" + ) + assertEquals( + "((((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiateBySquaring(Expr("57"), -8).expr, + "tried exponentiationBySquaring(57, -8)" + ) + } + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt new file mode 100644 index 000000000..054f0dc4c --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.functions.testUtils.t +import space.kscience.kmath.functions.testUtils.x +import space.kscience.kmath.functions.testUtils.y +import space.kscience.kmath.functions.testUtils.z +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +class LabeledConstructorsTest { + @Test + @UnstableKMathAPI + fun testDSL1() { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u, z to 3u) to 5, + mapOf(y to 1u) to -6, + ), + Int.algebra.labeledPolynomialSpace { + LabeledPolynomialDSL1 { + 5 { x pow 2u; z pow 3u } + (-6) { y pow 1u } + } + }, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to -1, + ), + Int.algebra.labeledPolynomialSpace { + LabeledPolynomialDSL1 { + 5 { } + (-6) { } + } + }, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to -1, + ), + Int.algebra.labeledPolynomialSpace { + LabeledPolynomialDSL1 { + 5 { x pow 1u; x pow 1u } + (-6) { x pow 2u } + } + }, + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to -1, + ), + Int.algebra.labeledPolynomialSpace { + LabeledPolynomialDSL1 { + 5 { x pow 1u; x pow 1u } + (-6) { x pow 2u; z pow 0u } + } + }, + "test 3" + ) + } + @Test + @UnstableKMathAPI + fun testFabric() { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u, z to 3u) to 5, + mapOf(y to 1u) to -6, + ), + Int.algebra { + LabeledPolynomial( + mapOf(x to 2u, z to 3u) to 5, + mapOf(y to 1u) to -6, + ) + }, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u, z to 3u) to 5, + mapOf(y to 1u) to -6, + ), + Int.algebra { + LabeledPolynomial( + mapOf(x to 2u, y to 0u, z to 3u, t to 0u) to 5, + mapOf(x to 0u, y to 1u, z to 0u, t to 0u) to -6, + ) + }, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to -1, + ), + Int.algebra { + LabeledPolynomial( + mapOf(x to 0u) to 5, + mapOf(y to 0u, z to 0u) to -6, + ) + }, + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 0, + ), + Int.algebra { + LabeledPolynomial( + mapOf(x to 0u) to 5, + mapOf(z to 0u, t to 0u) to -5, + ) + }, + "test 4" + ) + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt new file mode 100644 index 000000000..bb30f7742 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt @@ -0,0 +1,2555 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.functions.testUtils.IntModuloRing +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.functions.testUtils.iota +import space.kscience.kmath.functions.testUtils.m +import space.kscience.kmath.functions.testUtils.o +import space.kscience.kmath.functions.testUtils.s +import space.kscience.kmath.functions.testUtils.t +import space.kscience.kmath.functions.testUtils.x +import space.kscience.kmath.functions.testUtils.y +import space.kscience.kmath.functions.testUtils.z +import kotlin.test.* + + +// TODO: Тесты на конвертацию. +class LabeledPolynomialTest { + @Test + fun test_Variable_Int_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(1), + ), + x + 5, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + ), + x + 0, + "test 2" + ) + } + } + @Test + fun test_Variable_Int_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-5), + mapOf(x to 1u) to Rational(1), + ), + x - 5, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + ), + x - 0, + "test 2" + ) + } + } + @Test + fun test_Variable_Int_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(5), + ), + x * 5, + "test 1" + ) + assertSame( + zero, + x * 0, + "test 2" + ) + } + } + @Test + fun test_Int_Variable_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(1), + ), + 5 + x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + ), + 0 + x, + "test 2" + ) + } + } + @Test + fun test_Int_Variable_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(-1), + ), + 5 - x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-1), + ), + 0 - x, + "test 2" + ) + } + } + @Test + fun test_Int_Variable_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(5), + ), + 5 * x, + "test 1" + ) + assertSame( + zero, + 0 * x, + "test 2" + ) + } + } + @Test + fun test_Polynomial_Int_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + -3, + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + -3, + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + -3, + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ) + -3, + "test 4" + ) + val polynomial_5 = LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + polynomial_5 + 0, + "test 5" + ) + val polynomial_6 = LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + polynomial_6 + 0, + "test 6" + ) + val polynomial_7 = LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + polynomial_7 + 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - 3, + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - 3, + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - 3, + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ) - 3, + "test 4" + ) + val polynomial_5 = LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + polynomial_5 - 0, + "test 5" + ) + val polynomial_6 = LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + polynomial_6 - 0, + "test 6" + ) + val polynomial_7 = LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + polynomial_7 - 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to m(34), + mapOf(x to 3u) to m(2), + mapOf(x to 0u, y to 1u) to m(1), + mapOf(x to 1u) to m(20), + mapOf(x to 0u, y to 0u, z to 2u) to m(2), + ), + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) * 27, + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + LabeledPolynomial( + mapOf() to m(7), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(49), + mapOf(x to 1u) to m(21), + mapOf(x to 0u, y to 0u, z to 2u) to m(14), + ) * 15, + "test 2" + ) + val polynomial = LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) + assertSame( + zero, + polynomial * 0, + "test 3" + ) + assertSame( + polynomial, + polynomial * 1, + "test 4" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + -3 + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + -3 + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + -3 + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + -3 + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + "test 4" + ) + val polynomial_5 = LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + 0 + polynomial_5, + "test 5" + ) + val polynomial_6 = LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + 0 + polynomial_6, + "test 6" + ) + val polynomial_7 = LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + 0 + polynomial_7, + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(22, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 3 - LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(3, 1), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 3 - LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 3 - LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + 3 - LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(22, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 0 - LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 0 - LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + LabeledPolynomial( + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + 0 - LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to m(34), + mapOf(x to 3u) to m(2), + mapOf(x to 0u, y to 1u) to m(1), + mapOf(x to 1u) to m(20), + mapOf(x to 0u, y to 0u, z to 2u) to m(2), + ), + 27 * LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + 15 * LabeledPolynomial( + mapOf() to m(7), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(49), + mapOf(x to 1u) to m(21), + mapOf(x to 0u, y to 0u, z to 2u) to m(14), + ), + "test 2" + ) + val polynomial = LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) + assertSame( + zero, + 0 * polynomial, + "test 3" + ) + assertSame( + polynomial, + 1 * polynomial, + "test 4" + ) + } + } + @Test + fun test_Variable_Constant_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(1), + ), + x + Rational(5), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(1), + ), + x + Rational(0), + "test 2" + ) + } + } + @Test + fun test_Variable_Constant_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-5), + mapOf(x to 1u) to Rational(1), + ), + x - Rational(5), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(1), + ), + x - Rational(0), + "test 2" + ) + } + } + @Test + fun test_Variable_Constant_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(5), + ), + x * Rational(5), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(0), + ), + x * Rational(0), + "test 2" + ) + } + } + @Test + fun test_Constant_Variable_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(1), + ), + Rational(5) + x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(1), + ), + Rational(0) + x, + "test 2" + ) + } + } + @Test + fun test_Constant_Variable_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(5), + mapOf(x to 1u) to Rational(-1), + ), + Rational(5) - x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(-1), + ), + Rational(0) - x, + "test 2" + ) + } + } + @Test + fun test_Constant_Variable_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(5), + ), + Rational(5) * x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(0), + ), + Rational(0) * x, + "test 2" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ) + Rational(-3), + "test 4" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(0), + "test 5" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(0), + "test 6" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) + Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(3), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(3), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(3), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ) - Rational(3), + "test 4" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(0), + "test 5" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(0), + "test 6" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ) - Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to m(34), + mapOf(x to 3u) to m(2), + mapOf(x to 0u, y to 1u) to m(1), + mapOf(x to 1u) to m(20), + mapOf(x to 0u, y to 0u, z to 2u) to m(2), + ), + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) * m(27), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + LabeledPolynomial( + mapOf() to m(7), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(49), + mapOf(x to 1u) to m(21), + mapOf(x to 0u, y to 0u, z to 2u) to m(14), + ) * m(15), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) * m(0), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ) * m(1), + "test 4" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(-3) + LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-3, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(-3) + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(-3) + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + Rational(-3) + LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(0) + LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(0) + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + Rational(0) + LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(22, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(3) - LabeledPolynomial( + mapOf() to Rational(5, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(3, 1), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(3) - LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 1), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(3) - LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + Rational(3) - LabeledPolynomial( + mapOf() to Rational(27, 9), + mapOf(x to 3u) to Rational(0), + mapOf(x to 0u, y to 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(22, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(0) - LabeledPolynomial( + mapOf() to Rational(-22, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(0) - LabeledPolynomial( + mapOf() to Rational(0, 9), + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 3u) to Rational(8, 9), + mapOf(x to 0u, y to 4u) to Rational(8, 7), + ), + Rational(0) - LabeledPolynomial( + mapOf(x to 3u) to Rational(-8, 9), + mapOf(x to 0u, y to 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to m(34), + mapOf(x to 3u) to m(2), + mapOf(x to 0u, y to 1u) to m(1), + mapOf(x to 1u) to m(20), + mapOf(x to 0u, y to 0u, z to 2u) to m(2), + ), + m(27) * LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + m(15) * LabeledPolynomial( + mapOf() to m(7), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(49), + mapOf(x to 1u) to m(21), + mapOf(x to 0u, y to 0u, z to 2u) to m(14), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(0), + mapOf(x to 3u) to m(0), + mapOf(x to 0u, y to 1u) to m(0), + mapOf(x to 1u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + ), + m(0) * LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + m(1) * LabeledPolynomial( + mapOf() to m(22), + mapOf(x to 3u) to m(26), + mapOf(x to 0u, y to 1u) to m(13), + mapOf(x to 1u) to m(15), + mapOf(x to 0u, y to 0u, z to 2u) to m(26), + ), + "test 4" + ) + } + } + @Test + fun test_Variable_unaryPlus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + ), + +x + ) + } + } + @Test + fun test_Variable_unaryMinus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-1), + ), + -x + ) + } + } + @Test + fun test_Variable_Variable_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(y to 1u) to Rational(1), + ), + x + y, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(2), + ), + x + x, + "test 2" + ) + } + } + @Test + fun test_Variable_Variable_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(y to 1u) to Rational(-1), + ), + x - y, + "test 1" + ) + assertSame( + zero, + x - x, + "test 2" + ) + } + } + @Test + fun test_Variable_Variable_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u, y to 1u) to Rational(1), + ), + x * y, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(1), + ), + x * x, + "test 2" + ) + } + } + @Test + fun test_Variable_Polynomial_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(7, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + x + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(6, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + y + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + mapOf(iota to 1u) to Rational(1), + ), + iota + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 3" + ) + } + } + @Test + fun test_Variable_Polynomial_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(16, 4), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-3, 8), + mapOf(y to 1u) to Rational(1, 7), + mapOf(x to 1u, y to 1u) to Rational(15, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 5), + mapOf(y to 2u) to Rational(13, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(-11, 8), + ), + x - LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(16, 4), + mapOf(x to 1u) to Rational(-4, 3), + mapOf(x to 2u) to Rational(-3, 8), + mapOf(y to 1u) to Rational(8, 7), + mapOf(x to 1u, y to 1u) to Rational(15, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 5), + mapOf(y to 2u) to Rational(13, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(-11, 8), + ), + y - LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(16, 4), + mapOf(x to 1u) to Rational(-4, 3), + mapOf(x to 2u) to Rational(-3, 8), + mapOf(y to 1u) to Rational(1, 7), + mapOf(x to 1u, y to 1u) to Rational(15, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 5), + mapOf(y to 2u) to Rational(13, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(-11, 8), + mapOf(iota to 1u) to Rational(1), + ), + iota - LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 3" + ) + } + } + @Test + fun test_Variable_Polynomial_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-16, 4), + mapOf(x to 2u) to Rational(4, 3), + mapOf(x to 3u) to Rational(3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 7), + mapOf(x to 2u, y to 1u) to Rational(-15, 3), + mapOf(x to 3u, y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 2u) to Rational(-13, 3), + mapOf(x to 2u, y to 2u) to Rational(13, 4), + mapOf(x to 3u, y to 2u) to Rational(11, 8), + ), + x * LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(-16, 4), + mapOf(x to 1u, y to 1u) to Rational(4, 3), + mapOf(x to 2u, y to 1u) to Rational(3, 8), + mapOf(y to 2u) to Rational(-1, 7), + mapOf(x to 1u, y to 2u) to Rational(-15, 3), + mapOf(x to 2u, y to 2u) to Rational(6, 5), + mapOf(y to 3u) to Rational(-13, 3), + mapOf(x to 1u, y to 3u) to Rational(13, 4), + mapOf(x to 2u, y to 3u) to Rational(11, 8), + ), + y * LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(iota to 1u) to Rational(-16, 4), + mapOf(x to 1u, iota to 1u) to Rational(4, 3), + mapOf(x to 2u, iota to 1u) to Rational(3, 8), + mapOf(y to 1u, iota to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u, iota to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u, iota to 1u) to Rational(6, 5), + mapOf(y to 2u, iota to 1u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u, iota to 1u) to Rational(13, 4), + mapOf(x to 2u, y to 2u, iota to 1u) to Rational(11, 8), + ), + iota * LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + "test 3" + ) + } + } + @Test + fun test_Polynomial_Variable_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(7, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) + x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(6, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) + y, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + mapOf(iota to 1u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) + iota, + "test 3" + ) + } + } + @Test + fun test_Polynomial_Variable_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(1, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) - x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-8, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) - y, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + mapOf(iota to 1u) to Rational(-1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) - iota, + "test 3" + ) + } + } + @Test + fun test_Polynomial_Variable_times() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-16, 4), + mapOf(x to 2u) to Rational(4, 3), + mapOf(x to 3u) to Rational(3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 7), + mapOf(x to 2u, y to 1u) to Rational(-15, 3), + mapOf(x to 3u, y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 2u) to Rational(-13, 3), + mapOf(x to 2u, y to 2u) to Rational(13, 4), + mapOf(x to 3u, y to 2u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) * x, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(-16, 4), + mapOf(x to 1u, y to 1u) to Rational(4, 3), + mapOf(x to 2u, y to 1u) to Rational(3, 8), + mapOf(y to 2u) to Rational(-1, 7), + mapOf(x to 1u, y to 2u) to Rational(-15, 3), + mapOf(x to 2u, y to 2u) to Rational(6, 5), + mapOf(y to 3u) to Rational(-13, 3), + mapOf(x to 1u, y to 3u) to Rational(13, 4), + mapOf(x to 2u, y to 3u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) * y, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(iota to 1u) to Rational(-16, 4), + mapOf(x to 1u, iota to 1u) to Rational(4, 3), + mapOf(x to 2u, iota to 1u) to Rational(3, 8), + mapOf(y to 1u, iota to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u, iota to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u, iota to 1u) to Rational(6, 5), + mapOf(y to 2u, iota to 1u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u, iota to 1u) to Rational(13, 4), + mapOf(x to 2u, y to 2u, iota to 1u) to Rational(11, 8), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-16, 4), + mapOf(x to 1u) to Rational(4, 3), + mapOf(x to 2u) to Rational(3, 8), + mapOf(y to 1u) to Rational(-1, 7), + mapOf(x to 1u, y to 1u) to Rational(-15, 3), + mapOf(x to 2u, y to 1u) to Rational(6, 5), + mapOf(y to 2u) to Rational(-13, 3), + mapOf(x to 1u, y to 2u) to Rational(13, 4), + mapOf(x to 2u, y to 2u) to Rational(11, 8), + ) * iota, + "test 3" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf(x to 5u) to Rational(-5, 9), + mapOf() to Rational(8, 9), + mapOf(iota to 13u) to Rational(8, 7), + ), + -LabeledPolynomial( + mapOf(x to 5u) to Rational(5, 9), + mapOf() to Rational(-8, 9), + mapOf(iota to 13u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf(x to 5u) to Rational(-5, 9), + mapOf() to Rational(8, 9), + mapOf(iota to 13u) to Rational(8, 7), + mapOf(x to 0u, y to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + ), + -LabeledPolynomial( + mapOf(x to 5u) to Rational(5, 9), + mapOf() to Rational(-8, 9), + mapOf(iota to 13u) to Rational(-8, 7), + mapOf(x to 0u, y to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + ), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(146, 63), + mapOf(x to 1u, y to 1u) to Rational(-3, 5), + mapOf(x to 2u, y to 1u) to Rational(61, 15), + mapOf(x to 0u, y to 2u) to Rational(157, 63), + mapOf(x to 1u, y to 2u) to Rational(-55, 21), + mapOf(x to 2u, y to 2u) to Rational(11, 24), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(-7, 7), + mapOf(x to 2u, y to 1u) to Rational(12, 5), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) + LabeledPolynomial( + mapOf() to Rational(-20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(-20, 7), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(7, 9), + mapOf(x to 1u, y to 2u) to Rational(5, 7), + mapOf(x to 2u, y to 2u) to Rational(-2, 3), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(157, 63), + mapOf(x to 1u, y to 2u) to Rational(-55, 21), + mapOf(x to 2u, y to 2u) to Rational(11, 24), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) + LabeledPolynomial( + mapOf() to Rational(-20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(-20, 7), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(7, 9), + mapOf(x to 1u, y to 2u) to Rational(5, 7), + mapOf(x to 2u, y to 2u) to Rational(-2, 3), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) + LabeledPolynomial( + mapOf() to Rational(-20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(-20, 7), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 0u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 0u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(-7, 7), + mapOf(x to 2u, y to 1u) to Rational(12, 5), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) + LabeledPolynomial( + mapOf() to Rational(-6, 4), + mapOf(x to 1u) to Rational(2, 6), + mapOf(x to 2u) to Rational(-10, 6), + mapOf(x to 0u, y to 1u) to Rational(-17, 7), + mapOf(x to 1u, y to 1u) to Rational(7, 7), + mapOf(x to 2u, y to 1u) to Rational(-12, 5), + mapOf(x to 0u, y to 2u) to Rational(-12, 7), + mapOf(x to 1u, y to 2u) to Rational(10, 3), + mapOf(x to 2u, y to 2u) to Rational(-9, 8), + ), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(146, 63), + mapOf(x to 1u, y to 1u) to Rational(-3, 5), + mapOf(x to 2u, y to 1u) to Rational(61, 15), + mapOf(x to 0u, y to 2u) to Rational(157, 63), + mapOf(x to 1u, y to 2u) to Rational(-55, 21), + mapOf(x to 2u, y to 2u) to Rational(11, 24), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(-7, 7), + mapOf(x to 2u, y to 1u) to Rational(12, 5), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) - LabeledPolynomial( + mapOf() to Rational(20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(20, 7), + mapOf(x to 0u, y to 1u) to Rational(1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 5), + mapOf(x to 2u, y to 1u) to Rational(-10, 6), + mapOf(x to 0u, y to 2u) to Rational(-7, 9), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(2, 3), + ), + "test 1" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(157, 63), + mapOf(x to 1u, y to 2u) to Rational(-55, 21), + mapOf(x to 2u, y to 2u) to Rational(11, 24), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) - LabeledPolynomial( + mapOf() to Rational(20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(20, 7), + mapOf(x to 0u, y to 1u) to Rational(1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 5), + mapOf(x to 2u, y to 1u) to Rational(-10, 6), + mapOf(x to 0u, y to 2u) to Rational(-7, 9), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(2, 3), + ), + "test 2" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(-17, 2), + mapOf(x to 1u) to Rational(-1, 3), + mapOf(x to 2u) to Rational(-25, 21), + mapOf(x to 0u, y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(2, 5), + mapOf(x to 2u, y to 1u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) - LabeledPolynomial( + mapOf() to Rational(20, 2), + mapOf(x to 1u) to Rational(0, 9), + mapOf(x to 2u) to Rational(20, 7), + mapOf(x to 0u, y to 1u) to Rational(1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 5), + mapOf(x to 2u, y to 1u) to Rational(-10, 6), + mapOf(x to 0u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + ), + "test 3" + ) + assertEquals( + LabeledPolynomial( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 0u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 0u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + ), + LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(-7, 7), + mapOf(x to 2u, y to 1u) to Rational(12, 5), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ) - LabeledPolynomial( + mapOf() to Rational(6, 4), + mapOf(x to 1u) to Rational(-2, 6), + mapOf(x to 2u) to Rational(10, 6), + mapOf(x to 0u, y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(-7, 7), + mapOf(x to 2u, y to 1u) to Rational(12, 5), + mapOf(x to 0u, y to 2u) to Rational(12, 7), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(9, 8), + ), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).labeledPolynomialSpace { + // (p + q + r) * (p^2 + q^2 + r^2 - pq - pr - qr) = p^3 + q^3 + r^3 - 3pqr + assertEquals( + LabeledPolynomial( + mapOf(x to 3u) to m(1), + mapOf(x to 0u, y to 3u) to m(1), + mapOf(x to 0u, y to 0u, z to 3u) to m(1), + mapOf(x to 1u, y to 2u) to m(0), + mapOf(x to 0u, y to 1u, z to 2u) to m(0), + mapOf(x to 2u, y to 0u, z to 1u) to m(0), + mapOf(x to 1u, y to 0u, z to 2u) to m(0), + mapOf(x to 2u, y to 1u) to m(0), + mapOf(x to 0u, y to 2u, z to 1u) to m(0), + mapOf(x to 1u, y to 1u, z to 1u) to m(-3), + ), + LabeledPolynomial( + mapOf(x to 1u) to m(1), + mapOf(x to 0u, y to 1u) to m(1), + mapOf(x to 0u, y to 0u, z to 1u) to m(1), + ) * LabeledPolynomial( + mapOf(x to 2u) to m(1), + mapOf(x to 0u, y to 2u) to m(1), + mapOf(x to 0u, y to 0u, z to 2u) to m(1), + mapOf(x to 1u, y to 1u) to m(-1), + mapOf(x to 0u, y to 1u, z to 1u) to m(-1), + mapOf(x to 1u, y to 0u, z to 1u) to m(-1), + ), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + LabeledPolynomial( + mapOf(x to 2u) to m(0), + mapOf(x to 0u, y to 2u) to m(0), + mapOf(x to 0u, y to 0u, z to 2u) to m(0), + mapOf(x to 1u, y to 1u) to m(0), + mapOf(x to 0u, y to 1u, z to 1u) to m(0), + mapOf(x to 1u, y to 0u, z to 1u) to m(0), + ), + LabeledPolynomial( + mapOf(x to 1u) to m(5), + mapOf(x to 0u, y to 1u) to m(-25), + mapOf(x to 0u, y to 0u, z to 1u) to m(10), + ) * LabeledPolynomial( + mapOf(x to 1u) to m(21), + mapOf(x to 0u, y to 1u) to m(14), + mapOf(x to 0u, y to 0u, z to 1u) to m(-7), + ), + "test 2" + ) + } + } + @Test + fun test_degree() { + RationalField.labeledPolynomialSpace { + assertEquals( + -1, + LabeledPolynomial().degree, + "test 1" + ) + assertEquals( + 0, + LabeledPolynomial( + mapOf() to o + ).degree, + "test 2" + ) + assertEquals( + 6, + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).degree, + "test 3" + ) + assertEquals( + 4, + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).degree, + "test 4" + ) + assertEquals( + 3, + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).degree, + "test 5" + ) + assertEquals( + 4, + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).degree, + "test 6" + ) + } + } + @Test + fun test_degrees() { + RationalField.labeledPolynomialSpace { + assertEquals( + mapOf(), + LabeledPolynomial().degrees, + "test 1" + ) + assertEquals( + mapOf(), + LabeledPolynomial( + mapOf() to o + ).degrees, + "test 2" + ) + assertEquals( + mapOf(x to 1u, y to 2u, z to 3u), + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).degrees, + "test 3" + ) + assertEquals( + mapOf(y to 1u, z to 2u, t to 1u), + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).degrees, + "test 4" + ) + assertEquals( + mapOf(x to 2u, y to 1u, z to 1u), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).degrees, + "test 5" + ) + assertEquals( + mapOf(x to 2u, y to 2u, z to 2u, t to 4u), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).degrees, + "test 6" + ) + } + } + @Test + fun test_degreeBy() { + RationalField.labeledPolynomialSpace { + fun LabeledPolynomial.collectDegrees(variables: Set = this.variables + iota): Map = variables.associateWith { degreeBy(it) } + assertEquals( + mapOf(iota to 0u), + LabeledPolynomial().collectDegrees(), + "test 1" + ) + assertEquals( + mapOf(iota to 0u), + LabeledPolynomial( + mapOf() to o + ).collectDegrees(), + "test 2" + ) + assertEquals( + mapOf(x to 1u, y to 2u, z to 3u, iota to 0u), + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).collectDegrees(), + "test 3" + ) + assertEquals( + mapOf(y to 1u, z to 2u, t to 1u, iota to 0u), + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).collectDegrees(), + "test 4" + ) + assertEquals( + mapOf(x to 2u, y to 1u, z to 1u, iota to 0u), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).collectDegrees(), + "test 5" + ) + assertEquals( + mapOf(x to 2u, y to 2u, z to 2u, t to 4u, iota to 0u), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).collectDegrees(), + "test 6" + ) + } + } + @Test + fun test_degreeBy_Collection() { + RationalField.labeledPolynomialSpace { + fun LabeledPolynomial.checkDegreeBy(message: String? = null) { + val variables = variables.toList() + iota + val variablesCollectionSequence: Sequence> = sequence { + val appearances = MutableList(variables.size) { 0 } + while (true) { + yield( + buildList { + for ((variableIndex, count) in appearances.withIndex()) repeat(count) { add(variables[variableIndex]) } + } + ) + val indexChange = appearances.indexOfFirst { it < 4 } + if (indexChange == -1) break + appearances[indexChange] += 1 + for (index in 0 until indexChange) appearances[index] = 0 + } + } + for (variablesCollection in variablesCollectionSequence) { + val expected = coefficients.keys.maxOfOrNull { degs -> degs.filterKeys { it in variablesCollection }.values.sum() } ?: 0u + val actual = degreeBy(variablesCollection) + if (actual != expected) + fail("${message ?: ""} Incorrect answer for variable collection $variablesCollection: expected $expected, actual $actual") + } + } + LabeledPolynomial().checkDegreeBy("test 1") + LabeledPolynomial( + mapOf() to o + ).checkDegreeBy("test 2") + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).checkDegreeBy("test 3") + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).checkDegreeBy("test 4") + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).checkDegreeBy("test 5") + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).checkDegreeBy("test 6") + } + } + @Test + fun test_variables() { + RationalField.labeledPolynomialSpace { + assertEquals( + setOf(), + LabeledPolynomial().variables, + "test 1" + ) + assertEquals( + setOf(), + LabeledPolynomial( + mapOf() to o + ).variables, + "test 2" + ) + assertEquals( + setOf(x, y, z), + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).variables, + "test 3" + ) + assertEquals( + setOf(y, z, t), + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).variables, + "test 4" + ) + assertEquals( + setOf(x, y, z), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).variables, + "test 5" + ) + assertEquals( + setOf(x, y, z, t), + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).variables, + "test 6" + ) + } + } + @Test + fun test_countOfVariables() { + RationalField.labeledPolynomialSpace { + assertEquals( + 0, + LabeledPolynomial().countOfVariables, + "test 1" + ) + assertEquals( + 0, + LabeledPolynomial( + mapOf() to o + ).countOfVariables, + "test 2" + ) + assertEquals( + 3, + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ).countOfVariables, + "test 3" + ) + assertEquals( + 3, + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u, t to 1u, s to 0u) to o + ).countOfVariables, + "test 4" + ) + assertEquals( + 3, + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ).countOfVariables, + "test 5" + ) + assertEquals( + 4, + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ).countOfVariables, + "test 6" + ) + } + } + @Test + fun test_RF_countOfVariables() { + RationalField.labeledRationalFunctionSpace { + assertEquals( + 0, + LabeledRationalFunction( + LabeledPolynomial() + ).countOfVariables, + "test 1" + ) + assertEquals( + 0, + LabeledRationalFunction( + LabeledPolynomial(), + LabeledPolynomial() + ).countOfVariables, + "test 2" + ) + assertEquals( + 0, + LabeledRationalFunction( + LabeledPolynomial( + mapOf() to o + ) + ).countOfVariables, + "test 3" + ) + assertEquals( + 3, + LabeledRationalFunction( + LabeledPolynomial( + mapOf(x to 1u, y to 2u, z to 3u) to o + ) + ).countOfVariables, + "test 4" + ) + assertEquals( + 3, + LabeledRationalFunction( + LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 0u, t to 1u) to o + ), + LabeledPolynomial( + mapOf(x to 0u, y to 0u, z to 2u) to o + ) + ).countOfVariables, + "test 5" + ) + assertEquals( + 3, + LabeledRationalFunction( + LabeledPolynomial( + mapOf() to o, + mapOf(x to 0u, y to 1u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ) + ).countOfVariables, + "test 6" + ) + assertEquals( + 4, + LabeledRationalFunction( + LabeledPolynomial( + mapOf() to o, + mapOf(x to 1u, y to 2u) to o, + mapOf(x to 2u, y to 0u, z to 1u) to o, + ), LabeledPolynomial( + mapOf(x to 0u, y to 1u, z to 2u) to o, + mapOf(x to 0u, y to 0u, z to 0u, t to 4u) to o, + ) + ).countOfVariables, + "test 7" + ) + } + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt new file mode 100644 index 000000000..637981b66 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -0,0 +1,8222 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.functions.testUtils.assertEquals +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.functions.testUtils.iota +import space.kscience.kmath.functions.testUtils.x +import space.kscience.kmath.functions.testUtils.y +import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + +class LabeledPolynomialUtilTest { + @Test + fun test_Polynomial_substitute_Double() { + assertEquals( + LabeledPolynomialAsIs(emptyMap() to 0.0), + LabeledPolynomialAsIs( + mapOf() to 1.0, + mapOf(x to 1u) to -2.0, + mapOf(x to 2u) to 1.0, + ).substitute(mapOf( + x to 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf()), + 0.001, + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + iota to 0.9211194782050933 + )), + 0.001, + "test 2'" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(y to 2u) to 0.2700930201481795, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + x to 0.0 + )), + 0.001, + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(y to 2u) to 0.2700930201481795, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + x to 0.0, + iota to 0.9211194782050933 + )), + 0.001, + "test 3'" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 1.433510890645169, + mapOf(x to 1u) to 0.6264844682514724, + mapOf(x to 2u) to 0.8405727903771333, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + y to 0.8400458576651112 + )), + 0.001, + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 1.433510890645169, + mapOf(x to 1u) to 0.6264844682514724, + mapOf(x to 2u) to 0.8405727903771333, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + y to 0.8400458576651112, + iota to 0.9211194782050933 + )), + 0.001, + "test 4'" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 1.934530767358133, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + x to 0.4846192734143442, + y to 0.8400458576651112, + )), + 0.001, + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to 1.934530767358133, + ), + LabeledPolynomialAsIs( + mapOf() to 0.8597048543814783, + mapOf(x to 1u) to 0.22997637465889875, + mapOf(x to 2u) to 0.32675302591924016, + mapOf(y to 1u) to 0.4561746111587508, + mapOf(x to 1u, y to 1u) to 0.5304946210170756, + mapOf(x to 2u, y to 1u) to 0.6244313712888998, + mapOf(y to 2u) to 0.2700930201481795, + mapOf(x to 1u, y to 2u) to -0.06962351375204712, + mapOf(x to 2u, y to 2u) to -0.015206988092131501, + ).substitute(mapOf( + x to 0.4846192734143442, + y to 0.8400458576651112, + iota to 0.9211194782050933 + )), + 0.001, + "test 5'" + ) + } + @Test + fun test_Polynomial_substitute_Constant_Map() { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ).substitute(RationalField, mapOf( + x to Rational(1) + )), + "test 1" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5%2C+y+%3D+12%2F9 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(143, 150) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to Rational(-2, 5), + y to Rational(12, 9), + )), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(143, 150) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to Rational(-2, 5), + y to Rational(12, 9), + iota to Rational(57, 179), + )), + "test 2'" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+y+%3D+12%2F9 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-67, 18), + mapOf(x to 1u) to Rational(-70, 9), + mapOf(x to 2u) to Rational(88, 9), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + y to Rational(12, 9), + )), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-67, 18), + mapOf(x to 1u) to Rational(-70, 9), + mapOf(x to 2u) to Rational(88, 9), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + y to Rational(12, 9), + iota to Rational(57, 179), + )), + "test 3'" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-83, 50), + mapOf(y to 1u) to Rational(29, 25), + mapOf(y to 2u) to Rational(3, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to Rational(-2, 5), + )), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-83, 50), + mapOf(y to 1u) to Rational(29, 25), + mapOf(y to 2u) to Rational(3, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to Rational(-2, 5), + iota to Rational(57, 179), + )), + "test 4'" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf()), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + iota to Rational(57, 179), + )), + "test 5'" + ) + // https://www.wolframalpha.com/input?i=%28%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2%29+p%5E8+where+x+%3D+q%2Fp%2C+y+%3D+x%5E3%2C+p+%3D+-2%2F5%2C+q+%3D+12%2F9 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(47639065216, 2562890625) + ), + LabeledPolynomialAsIs( + mapOf(x to 8u) to Rational(-3, 2), + mapOf(x to 7u, y to 1u) to Rational(8, 6), + mapOf(x to 6u, y to 2u) to Rational(14, 6), + mapOf(x to 5u, y to 3u) to Rational(-3, 1), + mapOf(x to 4u, y to 4u) to Rational(-19, 2), + mapOf(x to 3u, y to 5u) to Rational(9, 4), + mapOf(x to 2u, y to 6u) to Rational(5, 5), + mapOf(x to 1u, y to 7u) to Rational(18, 9), + mapOf(y to 8u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to Rational(-2, 5), + y to Rational(12, 9), + )), + "test 6" + ) + } + @Test + fun test_Polynomial_substitute_Polynomial_Map() { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + )), + "test 1" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-5%2F1+s+%2B+2%2F8+t%2C+y+%3D+11%2F7+t + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(y to 1u) to Rational(-92, 21), + mapOf(y to 2u) to Rational(-2627, 2352), + mapOf(y to 3u) to Rational(4565, 3136), + mapOf(y to 4u) to Rational(605, 1568), + mapOf(x to 1u) to Rational(-20, 3), + mapOf(x to 1u, y to 1u) to Rational(1445, 21), + mapOf(x to 1u, y to 2u) to Rational(-13145, 392), + mapOf(x to 1u, y to 3u) to Rational(-3025, 196), + mapOf(x to 2u) to Rational(175, 3), + mapOf(x to 2u, y to 1u) to Rational(2475, 28), + mapOf(x to 2u, y to 2u) to Rational(15125, 98), + mapOf(x to 3u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-5, 1), + mapOf(y to 1u) to Rational(2, 8), + ), + y to LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(0, 5), + mapOf(y to 1u) to Rational(11, 7), + ), + )), + "test 2" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = (-9/2 + 2/7 s + 9/1 s^2) + (13/1 + -1/8 s + 2/8 s^2) t + (19/4 + 15/7 s + -19/4 s^2) t^2 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(129, 4), + mapOf(x to 1u) to Rational(48583, 336), + mapOf(x to 2u) to Rational(-913477, 1568), + mapOf(x to 3u) to Rational(-967567, 672), + mapOf(x to 4u) to Rational(4722043, 1344), + mapOf(x to 5u) to Rational(8855, 2), + mapOf(x to 6u) to Rational(-311971, 32), + mapOf(x to 7u) to Rational(-17325, 4), + mapOf(x to 8u) to Rational(19845, 2), + mapOf(y to 1u) to Rational(-827, 4), + mapOf(x to 1u, y to 1u) to Rational(191927, 840), + mapOf(x to 2u, y to 1u) to Rational(9592627, 2352), + mapOf(x to 3u, y to 1u) to Rational(-105400711, 53760), + mapOf(x to 4u, y to 1u) to Rational(-10054101459, 439040), + mapOf(x to 5u, y to 1u) to Rational(2127351, 128), + mapOf(x to 6u, y to 1u) to Rational(116680973, 3136), + mapOf(x to 7u, y to 1u) to Rational(-220445, 7), + mapOf(x to 8u, y to 1u) to Rational(-2655, 4), + mapOf(y to 2u) to Rational(30567, 100), + mapOf(x to 1u, y to 2u) to Rational(-156284953, 39200), + mapOf(x to 2u, y to 2u) to Rational(-57661541711, 6585600), + mapOf(x to 3u, y to 2u) to Rational(131931579, 3136), + mapOf(x to 4u, y to 2u) to Rational(98818124791, 3512320), + mapOf(x to 5u, y to 2u) to Rational(-94458855053, 878080), + mapOf(x to 6u, y to 2u) to Rational(13937705305, 1229312), + mapOf(x to 7u, y to 2u) to Rational(335706887, 21952), + mapOf(x to 8u, y to 2u) to Rational(23549165, 1568), + mapOf(y to 3u) to Rational(111367, 1400), + mapOf(x to 1u, y to 3u) to Rational(4937369, 700), + mapOf(x to 2u, y to 3u) to Rational(-4449423711, 274400), + mapOf(x to 3u, y to 3u) to Rational(-351873325703, 4390400), + mapOf(x to 4u, y to 3u) to Rational(23495875029, 307328), + mapOf(x to 5u, y to 3u) to Rational(17576300919, 878080), + mapOf(x to 6u, y to 3u) to Rational(230316993, 12544), + mapOf(x to 7u, y to 3u) to Rational(-191130515, 21952), + mapOf(x to 8u, y to 3u) to Rational(332435, 392), + mapOf(y to 4u) to Rational(-275084, 1225), + mapOf(x to 1u, y to 4u) to Rational(-266774603, 137200), + mapOf(x to 2u, y to 4u) to Rational(2176279167121, 30732800), + mapOf(x to 3u, y to 4u) to Rational(10904913303, 2195200), + mapOf(x to 4u, y to 4u) to Rational(-10769286147, 2195200), + mapOf(x to 5u, y to 4u) to Rational(-26277119793, 439040), + mapOf(x to 6u, y to 4u) to Rational(25859735869, 6146560), + mapOf(x to 7u, y to 4u) to Rational(38906289, 2744), + mapOf(x to 8u, y to 4u) to Rational(-3072025, 392), + mapOf(y to 5u) to Rational(9573, 98), + mapOf(x to 1u, y to 5u) to Rational(-4154651399, 548800), + mapOf(x to 2u, y to 5u) to Rational(3446069019, 548800), + mapOf(x to 3u, y to 5u) to Rational(-7851500623, 137200), + mapOf(x to 4u, y to 5u) to Rational(-53205142903, 1920800), + mapOf(x to 5u, y to 5u) to Rational(-31953611, 3430), + mapOf(x to 6u, y to 5u) to Rational(1447380313, 109760), + mapOf(x to 7u, y to 5u) to Rational(764158625, 21952), + mapOf(x to 8u, y to 5u) to Rational(1153515, 784), + mapOf(y to 6u) to Rational(1722351, 7840), + mapOf(x to 1u, y to 6u) to Rational(-164554821, 109760), + mapOf(x to 2u, y to 6u) to Rational(-79096147243, 7683200), + mapOf(x to 3u, y to 6u) to Rational(-624721089, 15680), + mapOf(x to 4u, y to 6u) to Rational(11147305567, 548800), + mapOf(x to 5u, y to 6u) to Rational(8318333679, 109760), + mapOf(x to 6u, y to 6u) to Rational(32981871553, 1536640), + mapOf(x to 7u, y to 6u) to Rational(-225359619, 21952), + mapOf(x to 8u, y to 6u) to Rational(-3973995, 392), + mapOf(y to 7u) to Rational(67203, 784), + mapOf(x to 1u, y to 7u) to Rational(39281469, 54880), + mapOf(x to 2u, y to 7u) to Rational(70162551, 27440), + mapOf(x to 3u, y to 7u) to Rational(413630709, 54880), + mapOf(x to 4u, y to 7u) to Rational(4640410269, 192080), + mapOf(x to 5u, y to 7u) to Rational(802712247, 54880), + mapOf(x to 6u, y to 7u) to Rational(-473517603, 27440), + mapOf(x to 7u, y to 7u) to Rational(-17055459, 1568), + mapOf(x to 8u, y to 7u) to Rational(-12825, 14), + mapOf(y to 8u) to Rational(16245, 1568), + mapOf(x to 1u, y to 8u) to Rational(503253, 2744), + mapOf(x to 2u, y to 8u) to Rational(125292591, 96040), + mapOf(x to 3u, y to 8u) to Rational(12033171, 2744), + mapOf(x to 4u, y to 8u) to Rational(154352673, 27440), + mapOf(x to 5u, y to 8u) to Rational(-1302291, 392), + mapOf(x to 6u, y to 8u) to Rational(-20265741, 1960), + mapOf(x to 7u, y to 8u) to Rational(-26163, 56), + mapOf(x to 8u, y to 8u) to Rational(146205, 32), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(0, 6), + mapOf(x to 1u) to Rational(14, 8), + mapOf(x to 2u) to Rational(-14, 2), + mapOf(y to 1u) to Rational(-3, 5), + mapOf(x to 1u, y to 1u) to Rational(11, 1), + mapOf(x to 2u, y to 1u) to Rational(3, 7), + mapOf(y to 2u) to Rational(-3, 7), + mapOf(x to 1u, y to 2u) to Rational(-18, 5), + mapOf(x to 2u, y to 2u) to Rational(-9, 1), + ), + y to LabeledPolynomialAsIs( + mapOf() to Rational(-9, 2), + mapOf(x to 1u) to Rational(2, 7), + mapOf(x to 2u) to Rational(9, 1), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-1, 8), + mapOf(x to 2u, y to 1u) to Rational(2, 8), + mapOf(y to 2u) to Rational(19, 4), + mapOf(x to 1u, y to 2u) to Rational(15, 7), + mapOf(x to 2u, y to 2u) to Rational(-19, 4), + ), + )), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(129, 4), + mapOf(x to 1u) to Rational(48583, 336), + mapOf(x to 2u) to Rational(-913477, 1568), + mapOf(x to 3u) to Rational(-967567, 672), + mapOf(x to 4u) to Rational(4722043, 1344), + mapOf(x to 5u) to Rational(8855, 2), + mapOf(x to 6u) to Rational(-311971, 32), + mapOf(x to 7u) to Rational(-17325, 4), + mapOf(x to 8u) to Rational(19845, 2), + mapOf(y to 1u) to Rational(-827, 4), + mapOf(x to 1u, y to 1u) to Rational(191927, 840), + mapOf(x to 2u, y to 1u) to Rational(9592627, 2352), + mapOf(x to 3u, y to 1u) to Rational(-105400711, 53760), + mapOf(x to 4u, y to 1u) to Rational(-10054101459, 439040), + mapOf(x to 5u, y to 1u) to Rational(2127351, 128), + mapOf(x to 6u, y to 1u) to Rational(116680973, 3136), + mapOf(x to 7u, y to 1u) to Rational(-220445, 7), + mapOf(x to 8u, y to 1u) to Rational(-2655, 4), + mapOf(y to 2u) to Rational(30567, 100), + mapOf(x to 1u, y to 2u) to Rational(-156284953, 39200), + mapOf(x to 2u, y to 2u) to Rational(-57661541711, 6585600), + mapOf(x to 3u, y to 2u) to Rational(131931579, 3136), + mapOf(x to 4u, y to 2u) to Rational(98818124791, 3512320), + mapOf(x to 5u, y to 2u) to Rational(-94458855053, 878080), + mapOf(x to 6u, y to 2u) to Rational(13937705305, 1229312), + mapOf(x to 7u, y to 2u) to Rational(335706887, 21952), + mapOf(x to 8u, y to 2u) to Rational(23549165, 1568), + mapOf(y to 3u) to Rational(111367, 1400), + mapOf(x to 1u, y to 3u) to Rational(4937369, 700), + mapOf(x to 2u, y to 3u) to Rational(-4449423711, 274400), + mapOf(x to 3u, y to 3u) to Rational(-351873325703, 4390400), + mapOf(x to 4u, y to 3u) to Rational(23495875029, 307328), + mapOf(x to 5u, y to 3u) to Rational(17576300919, 878080), + mapOf(x to 6u, y to 3u) to Rational(230316993, 12544), + mapOf(x to 7u, y to 3u) to Rational(-191130515, 21952), + mapOf(x to 8u, y to 3u) to Rational(332435, 392), + mapOf(y to 4u) to Rational(-275084, 1225), + mapOf(x to 1u, y to 4u) to Rational(-266774603, 137200), + mapOf(x to 2u, y to 4u) to Rational(2176279167121, 30732800), + mapOf(x to 3u, y to 4u) to Rational(10904913303, 2195200), + mapOf(x to 4u, y to 4u) to Rational(-10769286147, 2195200), + mapOf(x to 5u, y to 4u) to Rational(-26277119793, 439040), + mapOf(x to 6u, y to 4u) to Rational(25859735869, 6146560), + mapOf(x to 7u, y to 4u) to Rational(38906289, 2744), + mapOf(x to 8u, y to 4u) to Rational(-3072025, 392), + mapOf(y to 5u) to Rational(9573, 98), + mapOf(x to 1u, y to 5u) to Rational(-4154651399, 548800), + mapOf(x to 2u, y to 5u) to Rational(3446069019, 548800), + mapOf(x to 3u, y to 5u) to Rational(-7851500623, 137200), + mapOf(x to 4u, y to 5u) to Rational(-53205142903, 1920800), + mapOf(x to 5u, y to 5u) to Rational(-31953611, 3430), + mapOf(x to 6u, y to 5u) to Rational(1447380313, 109760), + mapOf(x to 7u, y to 5u) to Rational(764158625, 21952), + mapOf(x to 8u, y to 5u) to Rational(1153515, 784), + mapOf(y to 6u) to Rational(1722351, 7840), + mapOf(x to 1u, y to 6u) to Rational(-164554821, 109760), + mapOf(x to 2u, y to 6u) to Rational(-79096147243, 7683200), + mapOf(x to 3u, y to 6u) to Rational(-624721089, 15680), + mapOf(x to 4u, y to 6u) to Rational(11147305567, 548800), + mapOf(x to 5u, y to 6u) to Rational(8318333679, 109760), + mapOf(x to 6u, y to 6u) to Rational(32981871553, 1536640), + mapOf(x to 7u, y to 6u) to Rational(-225359619, 21952), + mapOf(x to 8u, y to 6u) to Rational(-3973995, 392), + mapOf(y to 7u) to Rational(67203, 784), + mapOf(x to 1u, y to 7u) to Rational(39281469, 54880), + mapOf(x to 2u, y to 7u) to Rational(70162551, 27440), + mapOf(x to 3u, y to 7u) to Rational(413630709, 54880), + mapOf(x to 4u, y to 7u) to Rational(4640410269, 192080), + mapOf(x to 5u, y to 7u) to Rational(802712247, 54880), + mapOf(x to 6u, y to 7u) to Rational(-473517603, 27440), + mapOf(x to 7u, y to 7u) to Rational(-17055459, 1568), + mapOf(x to 8u, y to 7u) to Rational(-12825, 14), + mapOf(y to 8u) to Rational(16245, 1568), + mapOf(x to 1u, y to 8u) to Rational(503253, 2744), + mapOf(x to 2u, y to 8u) to Rational(125292591, 96040), + mapOf(x to 3u, y to 8u) to Rational(12033171, 2744), + mapOf(x to 4u, y to 8u) to Rational(154352673, 27440), + mapOf(x to 5u, y to 8u) to Rational(-1302291, 392), + mapOf(x to 6u, y to 8u) to Rational(-20265741, 1960), + mapOf(x to 7u, y to 8u) to Rational(-26163, 56), + mapOf(x to 8u, y to 8u) to Rational(146205, 32), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(0, 6), + mapOf(x to 1u) to Rational(14, 8), + mapOf(x to 2u) to Rational(-14, 2), + mapOf(y to 1u) to Rational(-3, 5), + mapOf(x to 1u, y to 1u) to Rational(11, 1), + mapOf(x to 2u, y to 1u) to Rational(3, 7), + mapOf(y to 2u) to Rational(-3, 7), + mapOf(x to 1u, y to 2u) to Rational(-18, 5), + mapOf(x to 2u, y to 2u) to Rational(-9, 1), + ), + y to LabeledPolynomialAsIs( + mapOf() to Rational(-9, 2), + mapOf(x to 1u) to Rational(2, 7), + mapOf(x to 2u) to Rational(9, 1), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-1, 8), + mapOf(x to 2u, y to 1u) to Rational(2, 8), + mapOf(y to 2u) to Rational(19, 4), + mapOf(x to 1u, y to 2u) to Rational(15, 7), + mapOf(x to 2u, y to 2u) to Rational(-19, 4), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-11, 3), + mapOf(x to 1u) to Rational(5, 2), + mapOf(x to 2u) to Rational(13, 7), + mapOf(y to 1u) to Rational(16, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(6, 1), + mapOf(y to 2u) to Rational(-14, 3), + mapOf(x to 1u, y to 2u) to Rational(-2, 7), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + )), + "test 3'" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = s, y = (-9/2 + 2/7 s + 9/1 s^2) + (13/1 + -1/8 s + 2/8 s^2) t + (19/4 + 15/7 s + -19/4 s^2) t^2 + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(129, 4), + mapOf(x to 1u) to Rational(6817, 84), + mapOf(x to 2u) to Rational(-21445, 294), + mapOf(x to 3u) to Rational(-12151, 49), + mapOf(x to 4u) to Rational(-17789, 196), + mapOf(x to 5u) to Rational(1224, 7), + mapOf(x to 6u) to Rational(405, 2), + mapOf(y to 1u) to Rational(-156), + mapOf(x to 1u, y to 1u) to Rational(-2440, 7), + mapOf(x to 2u, y to 1u) to Rational(-1571, 112), + mapOf(x to 3u, y to 1u) to Rational(107515, 224), + mapOf(x to 4u, y to 1u) to Rational(64965, 112), + mapOf(x to 5u, y to 1u) to Rational(209, 56), + mapOf(x to 6u, y to 1u) to Rational(45, 4), + mapOf(y to 2u) to Rational(112), + mapOf(x to 1u, y to 2u) to Rational(1449, 8), + mapOf(x to 2u, y to 2u) to Rational(1306309, 3136), + mapOf(x to 3u, y to 2u) to Rational(483207, 1568), + mapOf(x to 4u, y to 2u) to Rational(1978437, 6272), + mapOf(x to 5u, y to 2u) to Rational(-18231, 224), + mapOf(x to 6u, y to 2u) to Rational(-6835, 32), + mapOf(y to 3u) to Rational(247, 2), + mapOf(x to 1u, y to 3u) to Rational(33771, 112), + mapOf(x to 2u, y to 3u) to Rational(2073, 7), + mapOf(x to 3u, y to 3u) to Rational(-23463, 224), + mapOf(x to 4u, y to 3u) to Rational(-33825, 112), + mapOf(x to 5u, y to 3u) to Rational(201, 224), + mapOf(x to 6u, y to 3u) to Rational(-95, 16), + mapOf(y to 4u) to Rational(361, 16), + mapOf(x to 1u, y to 4u) to Rational(3667, 56), + mapOf(x to 2u, y to 4u) to Rational(88729, 1568), + mapOf(x to 3u, y to 4u) to Rational(-2476, 49), + mapOf(x to 4u, y to 4u) to Rational(-23419, 196), + mapOf(x to 5u, y to 4u) to Rational(-323, 56), + mapOf(x to 6u, y to 4u) to Rational(1805, 32), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + y to LabeledPolynomialAsIs( + mapOf() to Rational(-9, 2), + mapOf(x to 1u) to Rational(2, 7), + mapOf(x to 2u) to Rational(9, 1), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-1, 8), + mapOf(x to 2u, y to 1u) to Rational(2, 8), + mapOf(y to 2u) to Rational(19, 4), + mapOf(x to 1u, y to 2u) to Rational(15, 7), + mapOf(x to 2u, y to 2u) to Rational(-19, 4), + ), + )), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(129, 4), + mapOf(x to 1u) to Rational(6817, 84), + mapOf(x to 2u) to Rational(-21445, 294), + mapOf(x to 3u) to Rational(-12151, 49), + mapOf(x to 4u) to Rational(-17789, 196), + mapOf(x to 5u) to Rational(1224, 7), + mapOf(x to 6u) to Rational(405, 2), + mapOf(y to 1u) to Rational(-156), + mapOf(x to 1u, y to 1u) to Rational(-2440, 7), + mapOf(x to 2u, y to 1u) to Rational(-1571, 112), + mapOf(x to 3u, y to 1u) to Rational(107515, 224), + mapOf(x to 4u, y to 1u) to Rational(64965, 112), + mapOf(x to 5u, y to 1u) to Rational(209, 56), + mapOf(x to 6u, y to 1u) to Rational(45, 4), + mapOf(y to 2u) to Rational(112), + mapOf(x to 1u, y to 2u) to Rational(1449, 8), + mapOf(x to 2u, y to 2u) to Rational(1306309, 3136), + mapOf(x to 3u, y to 2u) to Rational(483207, 1568), + mapOf(x to 4u, y to 2u) to Rational(1978437, 6272), + mapOf(x to 5u, y to 2u) to Rational(-18231, 224), + mapOf(x to 6u, y to 2u) to Rational(-6835, 32), + mapOf(y to 3u) to Rational(247, 2), + mapOf(x to 1u, y to 3u) to Rational(33771, 112), + mapOf(x to 2u, y to 3u) to Rational(2073, 7), + mapOf(x to 3u, y to 3u) to Rational(-23463, 224), + mapOf(x to 4u, y to 3u) to Rational(-33825, 112), + mapOf(x to 5u, y to 3u) to Rational(201, 224), + mapOf(x to 6u, y to 3u) to Rational(-95, 16), + mapOf(y to 4u) to Rational(361, 16), + mapOf(x to 1u, y to 4u) to Rational(3667, 56), + mapOf(x to 2u, y to 4u) to Rational(88729, 1568), + mapOf(x to 3u, y to 4u) to Rational(-2476, 49), + mapOf(x to 4u, y to 4u) to Rational(-23419, 196), + mapOf(x to 5u, y to 4u) to Rational(-323, 56), + mapOf(x to 6u, y to 4u) to Rational(1805, 32), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + y to LabeledPolynomialAsIs( + mapOf() to Rational(-9, 2), + mapOf(x to 1u) to Rational(2, 7), + mapOf(x to 2u) to Rational(9, 1), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-1, 8), + mapOf(x to 2u, y to 1u) to Rational(2, 8), + mapOf(y to 2u) to Rational(19, 4), + mapOf(x to 1u, y to 2u) to Rational(15, 7), + mapOf(x to 2u, y to 2u) to Rational(-19, 4), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-11, 3), + mapOf(x to 1u) to Rational(5, 2), + mapOf(x to 2u) to Rational(13, 7), + mapOf(y to 1u) to Rational(16, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(6, 1), + mapOf(y to 2u) to Rational(-14, 3), + mapOf(x to 1u, y to 2u) to Rational(-2, 7), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + )), + "test 4'" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = t + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(7, 3), + mapOf(x to 2u) to Rational(-35, 16), + mapOf(x to 3u) to Rational(-343, 6), + mapOf(x to 4u) to Rational(343, 3), + mapOf(y to 1u) to Rational(-19, 5), + mapOf(x to 1u, y to 1u) to Rational(-823, 120), + mapOf(x to 2u, y to 1u) to Rational(1232417, 6720), + mapOf(x to 3u, y to 1u) to Rational(-9863, 24), + mapOf(x to 4u, y to 1u) to Rational(385, 4), + mapOf(y to 2u) to Rational(2439, 350), + mapOf(x to 1u, y to 2u) to Rational(-5793, 40), + mapOf(x to 2u, y to 2u) to Rational(1172113, 3360), + mapOf(x to 3u, y to 2u) to Rational(-13531, 40), + mapOf(x to 4u, y to 2u) to Rational(2824, 7), + mapOf(y to 3u) to Rational(3417, 700), + mapOf(x to 1u, y to 3u) to Rational(1191, 200), + mapOf(x to 2u, y to 3u) to Rational(8383, 28), + mapOf(x to 3u, y to 3u) to Rational(-220279, 280), + mapOf(x to 4u, y to 3u) to Rational(49179, 196), + mapOf(y to 4u) to Rational(57, 35), + mapOf(x to 1u, y to 4u) to Rational(-33771, 700), + mapOf(x to 2u, y to 4u) to Rational(196279, 1225), + mapOf(x to 3u, y to 4u) to Rational(-32259, 140), + mapOf(x to 4u, y to 4u) to Rational(23868, 49), + mapOf(y to 5u) to Rational(333, 196), + mapOf(x to 1u, y to 5u) to Rational(-204, 35), + mapOf(x to 2u, y to 5u) to Rational(-307233, 2450), + mapOf(x to 3u, y to 5u) to Rational(-12492, 35), + mapOf(x to 4u, y to 5u) to Rational(4563, 28), + mapOf(y to 6u) to Rational(45, 98), + mapOf(x to 1u, y to 6u) to Rational(54, 7), + mapOf(x to 2u, y to 6u) to Rational(1809, 35), + mapOf(x to 3u, y to 6u) to Rational(162), + mapOf(x to 4u, y to 6u) to Rational(405, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(0, 6), + mapOf(x to 1u) to Rational(14, 8), + mapOf(x to 2u) to Rational(-14, 2), + mapOf(y to 1u) to Rational(-3, 5), + mapOf(x to 1u, y to 1u) to Rational(11, 1), + mapOf(x to 2u, y to 1u) to Rational(3, 7), + mapOf(y to 2u) to Rational(-3, 7), + mapOf(x to 1u, y to 2u) to Rational(-18, 5), + mapOf(x to 2u, y to 2u) to Rational(-9, 1), + ), + )), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(7, 3), + mapOf(x to 2u) to Rational(-35, 16), + mapOf(x to 3u) to Rational(-343, 6), + mapOf(x to 4u) to Rational(343, 3), + mapOf(y to 1u) to Rational(-19, 5), + mapOf(x to 1u, y to 1u) to Rational(-823, 120), + mapOf(x to 2u, y to 1u) to Rational(1232417, 6720), + mapOf(x to 3u, y to 1u) to Rational(-9863, 24), + mapOf(x to 4u, y to 1u) to Rational(385, 4), + mapOf(y to 2u) to Rational(2439, 350), + mapOf(x to 1u, y to 2u) to Rational(-5793, 40), + mapOf(x to 2u, y to 2u) to Rational(1172113, 3360), + mapOf(x to 3u, y to 2u) to Rational(-13531, 40), + mapOf(x to 4u, y to 2u) to Rational(2824, 7), + mapOf(y to 3u) to Rational(3417, 700), + mapOf(x to 1u, y to 3u) to Rational(1191, 200), + mapOf(x to 2u, y to 3u) to Rational(8383, 28), + mapOf(x to 3u, y to 3u) to Rational(-220279, 280), + mapOf(x to 4u, y to 3u) to Rational(49179, 196), + mapOf(y to 4u) to Rational(57, 35), + mapOf(x to 1u, y to 4u) to Rational(-33771, 700), + mapOf(x to 2u, y to 4u) to Rational(196279, 1225), + mapOf(x to 3u, y to 4u) to Rational(-32259, 140), + mapOf(x to 4u, y to 4u) to Rational(23868, 49), + mapOf(y to 5u) to Rational(333, 196), + mapOf(x to 1u, y to 5u) to Rational(-204, 35), + mapOf(x to 2u, y to 5u) to Rational(-307233, 2450), + mapOf(x to 3u, y to 5u) to Rational(-12492, 35), + mapOf(x to 4u, y to 5u) to Rational(4563, 28), + mapOf(y to 6u) to Rational(45, 98), + mapOf(x to 1u, y to 6u) to Rational(54, 7), + mapOf(x to 2u, y to 6u) to Rational(1809, 35), + mapOf(x to 3u, y to 6u) to Rational(162), + mapOf(x to 4u, y to 6u) to Rational(405, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(0, 6), + mapOf(x to 1u) to Rational(14, 8), + mapOf(x to 2u) to Rational(-14, 2), + mapOf(y to 1u) to Rational(-3, 5), + mapOf(x to 1u, y to 1u) to Rational(11, 1), + mapOf(x to 2u, y to 1u) to Rational(3, 7), + mapOf(y to 2u) to Rational(-3, 7), + mapOf(x to 1u, y to 2u) to Rational(-18, 5), + mapOf(x to 2u, y to 2u) to Rational(-9, 1), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-11, 3), + mapOf(x to 1u) to Rational(5, 2), + mapOf(x to 2u) to Rational(13, 7), + mapOf(y to 1u) to Rational(16, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(6, 1), + mapOf(y to 2u) to Rational(-14, 3), + mapOf(x to 1u, y to 2u) to Rational(-2, 7), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + )), + "test 5'" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 2), + mapOf(x to 1u) to Rational(8, 6), + mapOf(x to 2u) to Rational(14, 6), + mapOf(y to 1u) to Rational(-3, 1), + mapOf(x to 1u, y to 1u) to Rational(-19, 2), + mapOf(x to 2u, y to 1u) to Rational(9, 4), + mapOf(y to 2u) to Rational(5, 5), + mapOf(x to 1u, y to 2u) to Rational(18, 9), + mapOf(x to 2u, y to 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-11, 3), + mapOf(x to 1u) to Rational(5, 2), + mapOf(x to 2u) to Rational(13, 7), + mapOf(y to 1u) to Rational(16, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(6, 1), + mapOf(y to 2u) to Rational(-14, 3), + mapOf(x to 1u, y to 2u) to Rational(-2, 7), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + )), + "test 6'" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_Polynomial_substitute_RationalFunction_Map() { + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(-194071, 4900), + mapOf(x to 3u, y to 1u) to Rational(394811, 225), + mapOf(x to 2u, y to 2u) to Rational(-444183161, 66150), + mapOf(x to 1u, y to 3u) to Rational(70537618, 59535), + mapOf(y to 4u) to Rational(9655504, 2835), + ), + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(9, 1), + mapOf(x to 3u, y to 1u) to Rational(61, 1), + mapOf(x to 2u, y to 2u) to Rational(2137, 36), + mapOf(x to 1u, y to 3u) to Rational(-1342, 9), + mapOf(y to 4u) to Rational(484, 9), + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(17, 7), + mapOf(y to 1u) to Rational(-13, 1), + ), + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-18, 6), + mapOf(y to 1u) to Rational(11, 6), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(18, 5), + mapOf(y to 1u) to Rational(-16, 3), + ), + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-1, 1), + mapOf(y to 1u) to Rational(-4, 1), + ) + ), + )), + "test 2" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-6443599, 10000), + mapOf(x to 1u) to Rational(166251223, 210000), + mapOf(x to 2u) to Rational(-4606805099, 3528000), + mapOf(x to 3u) to Rational(51204379, 19600), + mapOf(x to 4u) to Rational(-529045460659, 277830000), + mapOf(x to 5u) to Rational(2630836709, 1488375), + mapOf(x to 6u) to Rational(-42675691369, 25004700), + mapOf(x to 7u) to Rational(495825223, 1250235), + mapOf(x to 8u) to Rational(-22531756, 1750329), + mapOf(y to 1u) to Rational(-2526552797, 420000), + mapOf(x to 1u, y to 1u) to Rational(31108840471, 2520000), + mapOf(x to 2u, y to 1u) to Rational(-4789740847, 1102500), + mapOf(x to 3u, y to 1u) to Rational(186594307807, 11340000), + mapOf(x to 4u, y to 1u) to Rational(-11677815943, 1488375), + mapOf(x to 5u, y to 1u) to Rational(-181118486447, 27783000), + mapOf(x to 6u, y to 1u) to Rational(-16123292162, 14586075), + mapOf(x to 7u, y to 1u) to Rational(-140339343808, 26254935), + mapOf(x to 8u, y to 1u) to Rational(4570171616, 5250987), + mapOf(y to 2u) to Rational(-181436530573, 10080000), + mapOf(x to 1u, y to 2u) to Rational(6700437957491, 105840000), + mapOf(x to 2u, y to 2u) to Rational(-3527267461, 1417500), + mapOf(x to 3u, y to 2u) to Rational(-38084563451, 5556600), + mapOf(x to 4u, y to 2u) to Rational(-565662040631, 13891500), + mapOf(x to 5u, y to 2u) to Rational(-35479071126397, 583443000), + mapOf(x to 6u, y to 2u) to Rational(-11717559078469, 525098700), + mapOf(x to 7u, y to 2u) to Rational(-2043385293517, 225042300), + mapOf(x to 8u, y to 2u) to Rational(-3644439630451, 551353635), + mapOf(y to 3u) to Rational(-1760423269, 126000), + mapOf(x to 1u, y to 3u) to Rational(310176758299, 2352000), + mapOf(x to 2u, y to 3u) to Rational(-907229584837, 21168000), + mapOf(x to 3u, y to 3u) to Rational(-16717135885963, 95256000), + mapOf(x to 4u, y to 3u) to Rational(-43762928025353, 333396000), + mapOf(x to 5u, y to 3u) to Rational(-328427480571607, 3000564000), + mapOf(x to 6u, y to 3u) to Rational(-7722675917197, 210039480), + mapOf(x to 7u, y to 3u) to Rational(1713350137019, 1225230300), + mapOf(x to 8u, y to 3u) to Rational(156695935643, 31505922), + mapOf(y to 4u) to Rational(18362364269, 1008000), + mapOf(x to 1u, y to 4u) to Rational(955674858553, 10584000), + mapOf(x to 2u, y to 4u) to Rational(-71937470607371, 444528000), + mapOf(x to 3u, y to 4u) to Rational(-34097985615163, 95256000), + mapOf(x to 4u, y to 4u) to Rational(-340736178775883, 2000376000), + mapOf(x to 5u, y to 4u) to Rational(-511324523441897, 10501974000), + mapOf(x to 6u, y to 4u) to Rational(-125375649409151, 8821658160), + mapOf(x to 7u, y to 4u) to Rational(-2813518533421, 1575296100), + mapOf(x to 8u, y to 4u) to Rational(-17044089109, 5250987), + mapOf(y to 5u) to Rational(600086461, 20160), + mapOf(x to 1u, y to 5u) to Rational(-18959931367, 423360), + mapOf(x to 2u, y to 5u) to Rational(-9178804929607, 44452800), + mapOf(x to 3u, y to 5u) to Rational(-1460114275979, 5334336), + mapOf(x to 4u, y to 5u) to Rational(-342533479090169, 4200789600), + mapOf(x to 5u, y to 5u) to Rational(20335453022963, 4200789600), + mapOf(x to 6u, y to 5u) to Rational(-21649775090197, 6301184400), + mapOf(x to 7u, y to 5u) to Rational(-197301716069, 131274675), + mapOf(x to 8u, y to 5u) to Rational(18711357470, 15752961), + mapOf(y to 6u) to Rational(621417991, 100800), + mapOf(x to 1u, y to 6u) to Rational(-159236792977, 2116800), + mapOf(x to 2u, y to 6u) to Rational(-6602528890883, 66679200), + mapOf(x to 3u, y to 6u) to Rational(-1086091664047, 19051200), + mapOf(x to 4u, y to 6u) to Rational(3769375009003, 1680315840), + mapOf(x to 5u, y to 6u) to Rational(-12920385574769, 1050197400), + mapOf(x to 6u, y to 6u) to Rational(-90219591809287, 6301184400), + mapOf(x to 7u, y to 6u) to Rational(656361553391, 1575296100), + mapOf(x to 8u, y to 6u) to Rational(757900793, 2250423), + mapOf(y to 7u) to Rational(-100770017, 15120), + mapOf(x to 1u, y to 7u) to Rational(-316364851, 17640), + mapOf(x to 2u, y to 7u) to Rational(-85118560057, 6667920), + mapOf(x to 3u, y to 7u) to Rational(6286563719, 416745), + mapOf(x to 4u, y to 7u) to Rational(26803885301, 1714608), + mapOf(x to 5u, y to 7u) to Rational(-13767154393, 4286520), + mapOf(x to 6u, y to 7u) to Rational(-3875138933, 1224720), + mapOf(x to 7u, y to 7u) to Rational(65193755, 333396), + mapOf(x to 8u, y to 7u) to Rational(90974351, 2500470), + mapOf(y to 8u) to Rational(-3182197, 1260), + mapOf(x to 1u, y to 8u) to Rational(24899923, 8820), + mapOf(x to 2u, y to 8u) to Rational(-19999556, 19845), + mapOf(x to 3u, y to 8u) to Rational(3276587, 3969), + mapOf(x to 4u, y to 8u) to Rational(13719549239, 5000940), + mapOf(x to 5u, y to 8u) to Rational(-961839938, 1250235), + mapOf(x to 6u, y to 8u) to Rational(-198184871, 833490), + mapOf(x to 7u, y to 8u) to Rational(230659711, 5000940), + mapOf(x to 8u, y to 8u) to Rational(292447, 35721) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(9, 100), + mapOf(x to 1u) to Rational(-21, 50), + mapOf(x to 2u) to Rational(293, 700), + mapOf(x to 3u) to Rational(29, 210), + mapOf(x to 4u) to Rational(3233, 8820), + mapOf(x to 5u) to Rational(-289, 441), + mapOf(x to 6u) to Rational(-1, 9), + mapOf(x to 7u) to Rational(-20, 441), + mapOf(x to 8u) to Rational(100, 441), + mapOf(y to 1u) to Rational(-57, 80), + mapOf(x to 1u, y to 1u) to Rational(-121, 400), + mapOf(x to 2u, y to 1u) to Rational(37117, 8400), + mapOf(x to 3u, y to 1u) to Rational(-4853, 3150), + mapOf(x to 4u, y to 1u) to Rational(1166203, 132300), + mapOf(x to 5u, y to 1u) to Rational(-2708, 567), + mapOf(x to 6u, y to 1u) to Rational(-287159, 416745), + mapOf(x to 7u, y to 1u) to Rational(-478204, 83349), + mapOf(x to 8u, y to 1u) to Rational(176320, 83349), + mapOf(y to 2u) to Rational(-6239, 6400), + mapOf(x to 1u, y to 2u) to Rational(264211, 11200), + mapOf(x to 2u, y to 2u) to Rational(-1591999, 100800), + mapOf(x to 3u, y to 2u) to Rational(12450091, 529200), + mapOf(x to 4u, y to 2u) to Rational(9230759, 226800), + mapOf(x to 5u, y to 2u) to Rational(18995554, 2083725), + mapOf(x to 6u, y to 2u) to Rational(136706258, 6251175), + mapOf(x to 7u, y to 2u) to Rational(-120907496, 3750705), + mapOf(x to 8u, y to 2u) to Rational(117200176, 15752961), + mapOf(y to 3u) to Rational(5653, 320), + mapOf(x to 1u, y to 3u) to Rational(-130853, 8400), + mapOf(x to 2u, y to 3u) to Rational(-20939327, 151200), + mapOf(x to 3u, y to 3u) to Rational(2566691, 25200), + mapOf(x to 4u, y to 3u) to Rational(-68441519, 476280), + mapOf(x to 5u, y to 3u) to Rational(2462904247, 12502350), + mapOf(x to 6u, y to 3u) to Rational(353667161, 18753525), + mapOf(x to 7u, y to 3u) to Rational(-1689134372, 26254935), + mapOf(x to 8u, y to 3u) to Rational(35084104, 2250423), + mapOf(y to 4u) to Rational(-3587, 300), + mapOf(x to 1u, y to 4u) to Rational(-10513243, 33600), + mapOf(x to 2u, y to 4u) to Rational(30766733, 176400), + mapOf(x to 3u, y to 4u) to Rational(-65680021, 198450), + mapOf(x to 4u, y to 4u) to Rational(-8108910547, 20003760), + mapOf(x to 5u, y to 4u) to Rational(2922125159, 6251175), + mapOf(x to 6u, y to 4u) to Rational(-4245279943, 131274675), + mapOf(x to 7u, y to 4u) to Rational(-371946872, 3750705), + mapOf(x to 8u, y to 4u) to Rational(61286752, 2250423), + mapOf(y to 5u) to Rational(-20477, 160), + mapOf(x to 1u, y to 5u) to Rational(215741, 1120), + mapOf(x to 2u, y to 5u) to Rational(30785843, 31752), + mapOf(x to 3u, y to 5u) to Rational(-357495959, 317520), + mapOf(x to 4u, y to 5u) to Rational(-1611242993, 10001880), + mapOf(x to 5u, y to 5u) to Rational(345925495, 500094), + mapOf(x to 6u, y to 5u) to Rational(-755948411, 3750705), + mapOf(x to 7u, y to 5u) to Rational(-108643496, 1250235), + mapOf(x to 8u, y to 5u) to Rational(1122512, 35721), + mapOf(y to 6u) to Rational(358037, 2880), + mapOf(x to 1u, y to 6u) to Rational(3895837, 3360), + mapOf(x to 2u, y to 6u) to Rational(359419201, 1270080), + mapOf(x to 3u, y to 6u) to Rational(-158522587, 105840), + mapOf(x to 4u, y to 6u) to Rational(10909002599, 20003760), + mapOf(x to 5u, y to 6u) to Rational(76846972, 138915), + mapOf(x to 6u, y to 6u) to Rational(-327696553, 1250235), + mapOf(x to 7u, y to 6u) to Rational(-1687328, 35721), + mapOf(x to 8u, y to 6u) to Rational(1016836, 35721), + mapOf(y to 7u) to Rational(658, 3), + mapOf(x to 1u, y to 7u) to Rational(48035, 168), + mapOf(x to 2u, y to 7u) to Rational(-5777875, 5292), + mapOf(x to 3u, y to 7u) to Rational(-7893899, 10584), + mapOf(x to 4u, y to 7u) to Rational(10191652, 11907), + mapOf(x to 5u, y to 7u) to Rational(2920121, 23814), + mapOf(x to 6u, y to 7u) to Rational(-2699780, 11907), + mapOf(x to 7u, y to 7u) to Rational(4556, 441), + mapOf(x to 8u, y to 7u) to Rational(3440, 189), + mapOf(y to 8u) to Rational(64, 1), + mapOf(x to 1u, y to 8u) to Rational(-808, 7), + mapOf(x to 2u, y to 8u) to Rational(-360895, 1764), + mapOf(x to 3u, y to 8u) to Rational(257657, 882), + mapOf(x to 4u, y to 8u) to Rational(3779917, 15876), + mapOf(x to 5u, y to 8u) to Rational(-610279, 3969), + mapOf(x to 6u, y to 8u) to Rational(-25091, 441), + mapOf(x to 7u, y to 8u) to Rational(9560, 567), + mapOf(x to 8u, y to 8u) to Rational(400, 81) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(17, 5), + mapOf(x to 1u) to Rational(11, 6), + mapOf(x to 2u) to Rational(14, 3), + mapOf(y to 1u) to Rational(17, 1), + mapOf(x to 1u, y to 1u) to Rational(12, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 2), + mapOf(y to 2u) to Rational(17, 1), + mapOf(x to 1u, y to 2u) to Rational(-4, 3), + mapOf(x to 2u, y to 2u) to Rational(2, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(3, 5), + mapOf(x to 1u) to Rational(3, 5), + mapOf(x to 2u) to Rational(3, 7), + mapOf(y to 1u) to Rational(-3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 1), + mapOf(x to 2u, y to 1u) to Rational(17, 9), + mapOf(y to 2u) to Rational(-8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 4), + mapOf(x to 2u, y to 2u) to Rational(10, 9), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(18, 5), + mapOf(x to 1u) to Rational(-17, 5), + mapOf(x to 2u) to Rational(-2, 7), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(-5, 1), + mapOf(x to 2u, y to 1u) to Rational(-9, 1), + mapOf(y to 2u) to Rational(-8, 8), + mapOf(x to 1u, y to 2u) to Rational(2, 7), + mapOf(x to 2u, y to 2u) to Rational(-13, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-4, 8), + mapOf(x to 1u) to Rational(15, 9), + mapOf(x to 2u) to Rational(-10, 9), + mapOf(y to 1u) to Rational(5, 3), + mapOf(x to 1u, y to 1u) to Rational(4, 1), + mapOf(x to 2u, y to 1u) to Rational(-2, 7), + mapOf(y to 2u) to Rational(2, 2), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(-18, 9), + ) + ), + )), + "test 3" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-6443599, 10000), + mapOf(x to 1u) to Rational(166251223, 210000), + mapOf(x to 2u) to Rational(-4606805099, 3528000), + mapOf(x to 3u) to Rational(51204379, 19600), + mapOf(x to 4u) to Rational(-529045460659, 277830000), + mapOf(x to 5u) to Rational(2630836709, 1488375), + mapOf(x to 6u) to Rational(-42675691369, 25004700), + mapOf(x to 7u) to Rational(495825223, 1250235), + mapOf(x to 8u) to Rational(-22531756, 1750329), + mapOf(y to 1u) to Rational(-2526552797, 420000), + mapOf(x to 1u, y to 1u) to Rational(31108840471, 2520000), + mapOf(x to 2u, y to 1u) to Rational(-4789740847, 1102500), + mapOf(x to 3u, y to 1u) to Rational(186594307807, 11340000), + mapOf(x to 4u, y to 1u) to Rational(-11677815943, 1488375), + mapOf(x to 5u, y to 1u) to Rational(-181118486447, 27783000), + mapOf(x to 6u, y to 1u) to Rational(-16123292162, 14586075), + mapOf(x to 7u, y to 1u) to Rational(-140339343808, 26254935), + mapOf(x to 8u, y to 1u) to Rational(4570171616, 5250987), + mapOf(y to 2u) to Rational(-181436530573, 10080000), + mapOf(x to 1u, y to 2u) to Rational(6700437957491, 105840000), + mapOf(x to 2u, y to 2u) to Rational(-3527267461, 1417500), + mapOf(x to 3u, y to 2u) to Rational(-38084563451, 5556600), + mapOf(x to 4u, y to 2u) to Rational(-565662040631, 13891500), + mapOf(x to 5u, y to 2u) to Rational(-35479071126397, 583443000), + mapOf(x to 6u, y to 2u) to Rational(-11717559078469, 525098700), + mapOf(x to 7u, y to 2u) to Rational(-2043385293517, 225042300), + mapOf(x to 8u, y to 2u) to Rational(-3644439630451, 551353635), + mapOf(y to 3u) to Rational(-1760423269, 126000), + mapOf(x to 1u, y to 3u) to Rational(310176758299, 2352000), + mapOf(x to 2u, y to 3u) to Rational(-907229584837, 21168000), + mapOf(x to 3u, y to 3u) to Rational(-16717135885963, 95256000), + mapOf(x to 4u, y to 3u) to Rational(-43762928025353, 333396000), + mapOf(x to 5u, y to 3u) to Rational(-328427480571607, 3000564000), + mapOf(x to 6u, y to 3u) to Rational(-7722675917197, 210039480), + mapOf(x to 7u, y to 3u) to Rational(1713350137019, 1225230300), + mapOf(x to 8u, y to 3u) to Rational(156695935643, 31505922), + mapOf(y to 4u) to Rational(18362364269, 1008000), + mapOf(x to 1u, y to 4u) to Rational(955674858553, 10584000), + mapOf(x to 2u, y to 4u) to Rational(-71937470607371, 444528000), + mapOf(x to 3u, y to 4u) to Rational(-34097985615163, 95256000), + mapOf(x to 4u, y to 4u) to Rational(-340736178775883, 2000376000), + mapOf(x to 5u, y to 4u) to Rational(-511324523441897, 10501974000), + mapOf(x to 6u, y to 4u) to Rational(-125375649409151, 8821658160), + mapOf(x to 7u, y to 4u) to Rational(-2813518533421, 1575296100), + mapOf(x to 8u, y to 4u) to Rational(-17044089109, 5250987), + mapOf(y to 5u) to Rational(600086461, 20160), + mapOf(x to 1u, y to 5u) to Rational(-18959931367, 423360), + mapOf(x to 2u, y to 5u) to Rational(-9178804929607, 44452800), + mapOf(x to 3u, y to 5u) to Rational(-1460114275979, 5334336), + mapOf(x to 4u, y to 5u) to Rational(-342533479090169, 4200789600), + mapOf(x to 5u, y to 5u) to Rational(20335453022963, 4200789600), + mapOf(x to 6u, y to 5u) to Rational(-21649775090197, 6301184400), + mapOf(x to 7u, y to 5u) to Rational(-197301716069, 131274675), + mapOf(x to 8u, y to 5u) to Rational(18711357470, 15752961), + mapOf(y to 6u) to Rational(621417991, 100800), + mapOf(x to 1u, y to 6u) to Rational(-159236792977, 2116800), + mapOf(x to 2u, y to 6u) to Rational(-6602528890883, 66679200), + mapOf(x to 3u, y to 6u) to Rational(-1086091664047, 19051200), + mapOf(x to 4u, y to 6u) to Rational(3769375009003, 1680315840), + mapOf(x to 5u, y to 6u) to Rational(-12920385574769, 1050197400), + mapOf(x to 6u, y to 6u) to Rational(-90219591809287, 6301184400), + mapOf(x to 7u, y to 6u) to Rational(656361553391, 1575296100), + mapOf(x to 8u, y to 6u) to Rational(757900793, 2250423), + mapOf(y to 7u) to Rational(-100770017, 15120), + mapOf(x to 1u, y to 7u) to Rational(-316364851, 17640), + mapOf(x to 2u, y to 7u) to Rational(-85118560057, 6667920), + mapOf(x to 3u, y to 7u) to Rational(6286563719, 416745), + mapOf(x to 4u, y to 7u) to Rational(26803885301, 1714608), + mapOf(x to 5u, y to 7u) to Rational(-13767154393, 4286520), + mapOf(x to 6u, y to 7u) to Rational(-3875138933, 1224720), + mapOf(x to 7u, y to 7u) to Rational(65193755, 333396), + mapOf(x to 8u, y to 7u) to Rational(90974351, 2500470), + mapOf(y to 8u) to Rational(-3182197, 1260), + mapOf(x to 1u, y to 8u) to Rational(24899923, 8820), + mapOf(x to 2u, y to 8u) to Rational(-19999556, 19845), + mapOf(x to 3u, y to 8u) to Rational(3276587, 3969), + mapOf(x to 4u, y to 8u) to Rational(13719549239, 5000940), + mapOf(x to 5u, y to 8u) to Rational(-961839938, 1250235), + mapOf(x to 6u, y to 8u) to Rational(-198184871, 833490), + mapOf(x to 7u, y to 8u) to Rational(230659711, 5000940), + mapOf(x to 8u, y to 8u) to Rational(292447, 35721) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(9, 100), + mapOf(x to 1u) to Rational(-21, 50), + mapOf(x to 2u) to Rational(293, 700), + mapOf(x to 3u) to Rational(29, 210), + mapOf(x to 4u) to Rational(3233, 8820), + mapOf(x to 5u) to Rational(-289, 441), + mapOf(x to 6u) to Rational(-1, 9), + mapOf(x to 7u) to Rational(-20, 441), + mapOf(x to 8u) to Rational(100, 441), + mapOf(y to 1u) to Rational(-57, 80), + mapOf(x to 1u, y to 1u) to Rational(-121, 400), + mapOf(x to 2u, y to 1u) to Rational(37117, 8400), + mapOf(x to 3u, y to 1u) to Rational(-4853, 3150), + mapOf(x to 4u, y to 1u) to Rational(1166203, 132300), + mapOf(x to 5u, y to 1u) to Rational(-2708, 567), + mapOf(x to 6u, y to 1u) to Rational(-287159, 416745), + mapOf(x to 7u, y to 1u) to Rational(-478204, 83349), + mapOf(x to 8u, y to 1u) to Rational(176320, 83349), + mapOf(y to 2u) to Rational(-6239, 6400), + mapOf(x to 1u, y to 2u) to Rational(264211, 11200), + mapOf(x to 2u, y to 2u) to Rational(-1591999, 100800), + mapOf(x to 3u, y to 2u) to Rational(12450091, 529200), + mapOf(x to 4u, y to 2u) to Rational(9230759, 226800), + mapOf(x to 5u, y to 2u) to Rational(18995554, 2083725), + mapOf(x to 6u, y to 2u) to Rational(136706258, 6251175), + mapOf(x to 7u, y to 2u) to Rational(-120907496, 3750705), + mapOf(x to 8u, y to 2u) to Rational(117200176, 15752961), + mapOf(y to 3u) to Rational(5653, 320), + mapOf(x to 1u, y to 3u) to Rational(-130853, 8400), + mapOf(x to 2u, y to 3u) to Rational(-20939327, 151200), + mapOf(x to 3u, y to 3u) to Rational(2566691, 25200), + mapOf(x to 4u, y to 3u) to Rational(-68441519, 476280), + mapOf(x to 5u, y to 3u) to Rational(2462904247, 12502350), + mapOf(x to 6u, y to 3u) to Rational(353667161, 18753525), + mapOf(x to 7u, y to 3u) to Rational(-1689134372, 26254935), + mapOf(x to 8u, y to 3u) to Rational(35084104, 2250423), + mapOf(y to 4u) to Rational(-3587, 300), + mapOf(x to 1u, y to 4u) to Rational(-10513243, 33600), + mapOf(x to 2u, y to 4u) to Rational(30766733, 176400), + mapOf(x to 3u, y to 4u) to Rational(-65680021, 198450), + mapOf(x to 4u, y to 4u) to Rational(-8108910547, 20003760), + mapOf(x to 5u, y to 4u) to Rational(2922125159, 6251175), + mapOf(x to 6u, y to 4u) to Rational(-4245279943, 131274675), + mapOf(x to 7u, y to 4u) to Rational(-371946872, 3750705), + mapOf(x to 8u, y to 4u) to Rational(61286752, 2250423), + mapOf(y to 5u) to Rational(-20477, 160), + mapOf(x to 1u, y to 5u) to Rational(215741, 1120), + mapOf(x to 2u, y to 5u) to Rational(30785843, 31752), + mapOf(x to 3u, y to 5u) to Rational(-357495959, 317520), + mapOf(x to 4u, y to 5u) to Rational(-1611242993, 10001880), + mapOf(x to 5u, y to 5u) to Rational(345925495, 500094), + mapOf(x to 6u, y to 5u) to Rational(-755948411, 3750705), + mapOf(x to 7u, y to 5u) to Rational(-108643496, 1250235), + mapOf(x to 8u, y to 5u) to Rational(1122512, 35721), + mapOf(y to 6u) to Rational(358037, 2880), + mapOf(x to 1u, y to 6u) to Rational(3895837, 3360), + mapOf(x to 2u, y to 6u) to Rational(359419201, 1270080), + mapOf(x to 3u, y to 6u) to Rational(-158522587, 105840), + mapOf(x to 4u, y to 6u) to Rational(10909002599, 20003760), + mapOf(x to 5u, y to 6u) to Rational(76846972, 138915), + mapOf(x to 6u, y to 6u) to Rational(-327696553, 1250235), + mapOf(x to 7u, y to 6u) to Rational(-1687328, 35721), + mapOf(x to 8u, y to 6u) to Rational(1016836, 35721), + mapOf(y to 7u) to Rational(658, 3), + mapOf(x to 1u, y to 7u) to Rational(48035, 168), + mapOf(x to 2u, y to 7u) to Rational(-5777875, 5292), + mapOf(x to 3u, y to 7u) to Rational(-7893899, 10584), + mapOf(x to 4u, y to 7u) to Rational(10191652, 11907), + mapOf(x to 5u, y to 7u) to Rational(2920121, 23814), + mapOf(x to 6u, y to 7u) to Rational(-2699780, 11907), + mapOf(x to 7u, y to 7u) to Rational(4556, 441), + mapOf(x to 8u, y to 7u) to Rational(3440, 189), + mapOf(y to 8u) to Rational(64, 1), + mapOf(x to 1u, y to 8u) to Rational(-808, 7), + mapOf(x to 2u, y to 8u) to Rational(-360895, 1764), + mapOf(x to 3u, y to 8u) to Rational(257657, 882), + mapOf(x to 4u, y to 8u) to Rational(3779917, 15876), + mapOf(x to 5u, y to 8u) to Rational(-610279, 3969), + mapOf(x to 6u, y to 8u) to Rational(-25091, 441), + mapOf(x to 7u, y to 8u) to Rational(9560, 567), + mapOf(x to 8u, y to 8u) to Rational(400, 81) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(17, 5), + mapOf(x to 1u) to Rational(11, 6), + mapOf(x to 2u) to Rational(14, 3), + mapOf(y to 1u) to Rational(17, 1), + mapOf(x to 1u, y to 1u) to Rational(12, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 2), + mapOf(y to 2u) to Rational(17, 1), + mapOf(x to 1u, y to 2u) to Rational(-4, 3), + mapOf(x to 2u, y to 2u) to Rational(2, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(3, 5), + mapOf(x to 1u) to Rational(3, 5), + mapOf(x to 2u) to Rational(3, 7), + mapOf(y to 1u) to Rational(-3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 1), + mapOf(x to 2u, y to 1u) to Rational(17, 9), + mapOf(y to 2u) to Rational(-8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 4), + mapOf(x to 2u, y to 2u) to Rational(10, 9), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(18, 5), + mapOf(x to 1u) to Rational(-17, 5), + mapOf(x to 2u) to Rational(-2, 7), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(-5, 1), + mapOf(x to 2u, y to 1u) to Rational(-9, 1), + mapOf(y to 2u) to Rational(-8, 8), + mapOf(x to 1u, y to 2u) to Rational(2, 7), + mapOf(x to 2u, y to 2u) to Rational(-13, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-4, 8), + mapOf(x to 1u) to Rational(15, 9), + mapOf(x to 2u) to Rational(-10, 9), + mapOf(y to 1u) to Rational(5, 3), + mapOf(x to 1u, y to 1u) to Rational(4, 1), + mapOf(x to 2u, y to 1u) to Rational(-2, 7), + mapOf(y to 2u) to Rational(2, 2), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(-18, 9), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 9), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(10, 9), + mapOf(y to 1u) to Rational(13, 3), + mapOf(x to 1u, y to 1u) to Rational(-12, 4), + mapOf(x to 2u, y to 1u) to Rational(3, 6), + mapOf(y to 2u) to Rational(2, 9), + mapOf(x to 1u, y to 2u) to Rational(7, 3), + mapOf(x to 2u, y to 2u) to Rational(16, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 2), + mapOf(x to 1u) to Rational(6, 2), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 5), + mapOf(y to 2u) to Rational(8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(17, 4), + ) + ) + )), + "test 3'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-66677, 3500), + mapOf(x to 1u) to Rational(-206281, 10500), + mapOf(x to 2u) to Rational(-412567, 7056), + mapOf(x to 3u) to Rational(-310081, 11025), + mapOf(x to 4u) to Rational(-575996, 15435), + mapOf(y to 1u) to Rational(-573701, 4200), + mapOf(x to 1u, y to 1u) to Rational(-2239001, 25200), + mapOf(x to 2u, y to 1u) to Rational(-8817889, 132300), + mapOf(x to 3u, y to 1u) to Rational(2317919, 44100), + mapOf(x to 4u, y to 1u) to Rational(1169471, 6615), + mapOf(y to 2u) to Rational(-4057819, 33600), + mapOf(x to 1u, y to 2u) to Rational(1373311, 12600), + mapOf(x to 2u, y to 2u) to Rational(32433493, 52920), + mapOf(x to 3u, y to 2u) to Rational(4998053, 33075), + mapOf(x to 4u, y to 2u) to Rational(-2147779, 8820), + mapOf(y to 3u) to Rational(2018481, 2240), + mapOf(x to 1u, y to 3u) to Rational(941713, 1440), + mapOf(x to 2u, y to 3u) to Rational(183749, 6615), + mapOf(x to 3u, y to 3u) to Rational(-4631023, 15876), + mapOf(x to 4u, y to 3u) to Rational(25609336, 178605), + mapOf(y to 4u) to Rational(11886431, 6720), + mapOf(x to 1u, y to 4u) to Rational(18433, 504), + mapOf(x to 2u, y to 4u) to Rational(-39613331, 45360), + mapOf(x to 3u, y to 4u) to Rational(681619, 5670), + mapOf(x to 4u, y to 4u) to Rational(-864841, 20412), + mapOf(y to 5u) to Rational(343535, 1008), + mapOf(x to 1u, y to 5u) to Rational(-33583, 72), + mapOf(x to 2u, y to 5u) to Rational(1194625, 9072), + mapOf(x to 3u, y to 5u) to Rational(-62917, 2268), + mapOf(x to 4u, y to 5u) to Rational(157645, 10206), + mapOf(y to 6u) to Rational(-1381, 3), + mapOf(x to 1u, y to 6u) to Rational(919, 36), + mapOf(x to 2u, y to 6u) to Rational(-3053, 36), + mapOf(x to 3u, y to 6u) to Rational(2125, 324), + mapOf(x to 4u, y to 6u) to Rational(-236, 243) + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-5, 3), + mapOf(x to 2u) to Rational(35, 9), + mapOf(x to 3u) to Rational(-100, 27), + mapOf(x to 4u) to Rational(100, 81), + mapOf(y to 1u) to Rational(-5, 3), + mapOf(x to 1u, y to 1u) to Rational(14, 9), + mapOf(x to 2u, y to 1u) to Rational(1874, 189), + mapOf(x to 3u, y to 1u) to Rational(-620, 63), + mapOf(x to 4u, y to 1u) to Rational(40, 63), + mapOf(y to 2u) to Rational(16, 9), + mapOf(x to 1u, y to 2u) to Rational(365, 21), + mapOf(x to 2u, y to 2u) to Rational(112, 9), + mapOf(x to 3u, y to 2u) to Rational(-464, 63), + mapOf(x to 4u, y to 2u) to Rational(1996, 441), + mapOf(y to 3u) to Rational(10, 3), + mapOf(x to 1u, y to 3u) to Rational(118, 21), + mapOf(x to 2u, y to 3u) to Rational(-272, 21), + mapOf(x to 3u, y to 3u) to Rational(-764, 49), + mapOf(x to 4u, y to 3u) to Rational(8, 7), + mapOf(y to 4u) to Rational(1, 1), + mapOf(x to 1u, y to 4u) to Rational(-10, 7), + mapOf(x to 2u, y to 4u) to Rational(-171, 49), + mapOf(x to 3u, y to 4u) to Rational(20, 7), + mapOf(x to 4u, y to 4u) to Rational(4, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(17, 5), + mapOf(x to 1u) to Rational(11, 6), + mapOf(x to 2u) to Rational(14, 3), + mapOf(y to 1u) to Rational(17, 1), + mapOf(x to 1u, y to 1u) to Rational(12, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 2), + mapOf(y to 2u) to Rational(17, 1), + mapOf(x to 1u, y to 2u) to Rational(-4, 3), + mapOf(x to 2u, y to 2u) to Rational(2, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(3, 5), + mapOf(x to 1u) to Rational(3, 5), + mapOf(x to 2u) to Rational(3, 7), + mapOf(y to 1u) to Rational(-3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 1), + mapOf(x to 2u, y to 1u) to Rational(17, 9), + mapOf(y to 2u) to Rational(-8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 4), + mapOf(x to 2u, y to 2u) to Rational(10, 9), + ) + ), + )), + "test 4" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-66677, 3500), + mapOf(x to 1u) to Rational(-206281, 10500), + mapOf(x to 2u) to Rational(-412567, 7056), + mapOf(x to 3u) to Rational(-310081, 11025), + mapOf(x to 4u) to Rational(-575996, 15435), + mapOf(y to 1u) to Rational(-573701, 4200), + mapOf(x to 1u, y to 1u) to Rational(-2239001, 25200), + mapOf(x to 2u, y to 1u) to Rational(-8817889, 132300), + mapOf(x to 3u, y to 1u) to Rational(2317919, 44100), + mapOf(x to 4u, y to 1u) to Rational(1169471, 6615), + mapOf(y to 2u) to Rational(-4057819, 33600), + mapOf(x to 1u, y to 2u) to Rational(1373311, 12600), + mapOf(x to 2u, y to 2u) to Rational(32433493, 52920), + mapOf(x to 3u, y to 2u) to Rational(4998053, 33075), + mapOf(x to 4u, y to 2u) to Rational(-2147779, 8820), + mapOf(y to 3u) to Rational(2018481, 2240), + mapOf(x to 1u, y to 3u) to Rational(941713, 1440), + mapOf(x to 2u, y to 3u) to Rational(183749, 6615), + mapOf(x to 3u, y to 3u) to Rational(-4631023, 15876), + mapOf(x to 4u, y to 3u) to Rational(25609336, 178605), + mapOf(y to 4u) to Rational(11886431, 6720), + mapOf(x to 1u, y to 4u) to Rational(18433, 504), + mapOf(x to 2u, y to 4u) to Rational(-39613331, 45360), + mapOf(x to 3u, y to 4u) to Rational(681619, 5670), + mapOf(x to 4u, y to 4u) to Rational(-864841, 20412), + mapOf(y to 5u) to Rational(343535, 1008), + mapOf(x to 1u, y to 5u) to Rational(-33583, 72), + mapOf(x to 2u, y to 5u) to Rational(1194625, 9072), + mapOf(x to 3u, y to 5u) to Rational(-62917, 2268), + mapOf(x to 4u, y to 5u) to Rational(157645, 10206), + mapOf(y to 6u) to Rational(-1381, 3), + mapOf(x to 1u, y to 6u) to Rational(919, 36), + mapOf(x to 2u, y to 6u) to Rational(-3053, 36), + mapOf(x to 3u, y to 6u) to Rational(2125, 324), + mapOf(x to 4u, y to 6u) to Rational(-236, 243) + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-5, 3), + mapOf(x to 2u) to Rational(35, 9), + mapOf(x to 3u) to Rational(-100, 27), + mapOf(x to 4u) to Rational(100, 81), + mapOf(y to 1u) to Rational(-5, 3), + mapOf(x to 1u, y to 1u) to Rational(14, 9), + mapOf(x to 2u, y to 1u) to Rational(1874, 189), + mapOf(x to 3u, y to 1u) to Rational(-620, 63), + mapOf(x to 4u, y to 1u) to Rational(40, 63), + mapOf(y to 2u) to Rational(16, 9), + mapOf(x to 1u, y to 2u) to Rational(365, 21), + mapOf(x to 2u, y to 2u) to Rational(112, 9), + mapOf(x to 3u, y to 2u) to Rational(-464, 63), + mapOf(x to 4u, y to 2u) to Rational(1996, 441), + mapOf(y to 3u) to Rational(10, 3), + mapOf(x to 1u, y to 3u) to Rational(118, 21), + mapOf(x to 2u, y to 3u) to Rational(-272, 21), + mapOf(x to 3u, y to 3u) to Rational(-764, 49), + mapOf(x to 4u, y to 3u) to Rational(8, 7), + mapOf(y to 4u) to Rational(1, 1), + mapOf(x to 1u, y to 4u) to Rational(-10, 7), + mapOf(x to 2u, y to 4u) to Rational(-171, 49), + mapOf(x to 3u, y to 4u) to Rational(20, 7), + mapOf(x to 4u, y to 4u) to Rational(4, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(17, 5), + mapOf(x to 1u) to Rational(11, 6), + mapOf(x to 2u) to Rational(14, 3), + mapOf(y to 1u) to Rational(17, 1), + mapOf(x to 1u, y to 1u) to Rational(12, 3), + mapOf(x to 2u, y to 1u) to Rational(-6, 2), + mapOf(y to 2u) to Rational(17, 1), + mapOf(x to 1u, y to 2u) to Rational(-4, 3), + mapOf(x to 2u, y to 2u) to Rational(2, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(3, 5), + mapOf(x to 1u) to Rational(3, 5), + mapOf(x to 2u) to Rational(3, 7), + mapOf(y to 1u) to Rational(-3, 8), + mapOf(x to 1u, y to 1u) to Rational(-1, 1), + mapOf(x to 2u, y to 1u) to Rational(17, 9), + mapOf(y to 2u) to Rational(-8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 4), + mapOf(x to 2u, y to 2u) to Rational(10, 9), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 9), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(10, 9), + mapOf(y to 1u) to Rational(13, 3), + mapOf(x to 1u, y to 1u) to Rational(-12, 4), + mapOf(x to 2u, y to 1u) to Rational(3, 6), + mapOf(y to 2u) to Rational(2, 9), + mapOf(x to 1u, y to 2u) to Rational(7, 3), + mapOf(x to 2u, y to 2u) to Rational(16, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 2), + mapOf(x to 1u) to Rational(6, 2), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 5), + mapOf(y to 2u) to Rational(8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(17, 4), + ) + ) + )), + "test 4'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(3539, 700), + mapOf(x to 1u) to Rational(-307079, 6300), + mapOf(x to 2u) to Rational(451609, 15120), + mapOf(x to 3u) to Rational(35287733, 396900), + mapOf(x to 4u) to Rational(-37242617, 396900), + mapOf(x to 5u) to Rational(382747, 19845), + mapOf(x to 6u) to Rational(-2407, 3969), + mapOf(y to 1u) to Rational(-226, 175), + mapOf(x to 1u, y to 1u) to Rational(-74113, 1890), + mapOf(x to 2u, y to 1u) to Rational(250931, 1764), + mapOf(x to 3u, y to 1u) to Rational(30071473, 99225), + mapOf(x to 4u, y to 1u) to Rational(-286466, 1323), + mapOf(x to 5u, y to 1u) to Rational(-2285282, 9261), + mapOf(x to 6u, y to 1u) to Rational(17900, 441), + mapOf(y to 2u) to Rational(3817, 3150), + mapOf(x to 1u, y to 2u) to Rational(577568, 11025), + mapOf(x to 2u, y to 2u) to Rational(9073553, 99225), + mapOf(x to 3u, y to 2u) to Rational(-1415849, 79380), + mapOf(x to 4u, y to 2u) to Rational(-124715629, 277830), + mapOf(x to 5u, y to 2u) to Rational(-1328953, 1890), + mapOf(x to 6u, y to 2u) to Rational(-297148, 1323), + mapOf(y to 3u) to Rational(6043, 945), + mapOf(x to 1u, y to 3u) to Rational(160381, 6615), + mapOf(x to 2u, y to 3u) to Rational(-673249, 13230), + mapOf(x to 3u, y to 3u) to Rational(-319255, 2058), + mapOf(x to 4u, y to 3u) to Rational(-98144, 1029), + mapOf(x to 5u, y to 3u) to Rational(-320239, 5145), + mapOf(x to 6u, y to 3u) to Rational(400, 147), + mapOf(y to 4u) to Rational(163, 63), + mapOf(x to 1u, y to 4u) to Rational(-25183, 4410), + mapOf(x to 2u, y to 4u) to Rational(-21369, 1372), + mapOf(x to 3u, y to 4u) to Rational(127499, 30870), + mapOf(x to 4u, y to 4u) to Rational(86971, 12348), + mapOf(x to 5u, y to 4u) to Rational(-11129, 1470), + mapOf(x to 6u, y to 4u) to Rational(544, 147) + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-5, 3), + mapOf(x to 2u) to Rational(35, 9), + mapOf(x to 3u) to Rational(-100, 27), + mapOf(x to 4u) to Rational(100, 81), + mapOf(y to 1u) to Rational(-5, 3), + mapOf(x to 1u, y to 1u) to Rational(14, 9), + mapOf(x to 2u, y to 1u) to Rational(1874, 189), + mapOf(x to 3u, y to 1u) to Rational(-620, 63), + mapOf(x to 4u, y to 1u) to Rational(40, 63), + mapOf(y to 2u) to Rational(16, 9), + mapOf(x to 1u, y to 2u) to Rational(365, 21), + mapOf(x to 2u, y to 2u) to Rational(112, 9), + mapOf(x to 3u, y to 2u) to Rational(-464, 63), + mapOf(x to 4u, y to 2u) to Rational(1996, 441), + mapOf(y to 3u) to Rational(10, 3), + mapOf(x to 1u, y to 3u) to Rational(118, 21), + mapOf(x to 2u, y to 3u) to Rational(-272, 21), + mapOf(x to 3u, y to 3u) to Rational(-764, 49), + mapOf(x to 4u, y to 3u) to Rational(8, 7), + mapOf(y to 4u) to Rational(1, 1), + mapOf(x to 1u, y to 4u) to Rational(-10, 7), + mapOf(x to 2u, y to 4u) to Rational(-171, 49), + mapOf(x to 3u, y to 4u) to Rational(20, 7), + mapOf(x to 4u, y to 4u) to Rational(4, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(18, 5), + mapOf(x to 1u) to Rational(-17, 5), + mapOf(x to 2u) to Rational(-2, 7), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(-5, 1), + mapOf(x to 2u, y to 1u) to Rational(-9, 1), + mapOf(y to 2u) to Rational(-8, 8), + mapOf(x to 1u, y to 2u) to Rational(2, 7), + mapOf(x to 2u, y to 2u) to Rational(-13, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-4, 8), + mapOf(x to 1u) to Rational(15, 9), + mapOf(x to 2u) to Rational(-10, 9), + mapOf(y to 1u) to Rational(5, 3), + mapOf(x to 1u, y to 1u) to Rational(4, 1), + mapOf(x to 2u, y to 1u) to Rational(-2, 7), + mapOf(y to 2u) to Rational(2, 2), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(-18, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(3539, 700), + mapOf(x to 1u) to Rational(-307079, 6300), + mapOf(x to 2u) to Rational(451609, 15120), + mapOf(x to 3u) to Rational(35287733, 396900), + mapOf(x to 4u) to Rational(-37242617, 396900), + mapOf(x to 5u) to Rational(382747, 19845), + mapOf(x to 6u) to Rational(-2407, 3969), + mapOf(y to 1u) to Rational(-226, 175), + mapOf(x to 1u, y to 1u) to Rational(-74113, 1890), + mapOf(x to 2u, y to 1u) to Rational(250931, 1764), + mapOf(x to 3u, y to 1u) to Rational(30071473, 99225), + mapOf(x to 4u, y to 1u) to Rational(-286466, 1323), + mapOf(x to 5u, y to 1u) to Rational(-2285282, 9261), + mapOf(x to 6u, y to 1u) to Rational(17900, 441), + mapOf(y to 2u) to Rational(3817, 3150), + mapOf(x to 1u, y to 2u) to Rational(577568, 11025), + mapOf(x to 2u, y to 2u) to Rational(9073553, 99225), + mapOf(x to 3u, y to 2u) to Rational(-1415849, 79380), + mapOf(x to 4u, y to 2u) to Rational(-124715629, 277830), + mapOf(x to 5u, y to 2u) to Rational(-1328953, 1890), + mapOf(x to 6u, y to 2u) to Rational(-297148, 1323), + mapOf(y to 3u) to Rational(6043, 945), + mapOf(x to 1u, y to 3u) to Rational(160381, 6615), + mapOf(x to 2u, y to 3u) to Rational(-673249, 13230), + mapOf(x to 3u, y to 3u) to Rational(-319255, 2058), + mapOf(x to 4u, y to 3u) to Rational(-98144, 1029), + mapOf(x to 5u, y to 3u) to Rational(-320239, 5145), + mapOf(x to 6u, y to 3u) to Rational(400, 147), + mapOf(y to 4u) to Rational(163, 63), + mapOf(x to 1u, y to 4u) to Rational(-25183, 4410), + mapOf(x to 2u, y to 4u) to Rational(-21369, 1372), + mapOf(x to 3u, y to 4u) to Rational(127499, 30870), + mapOf(x to 4u, y to 4u) to Rational(86971, 12348), + mapOf(x to 5u, y to 4u) to Rational(-11129, 1470), + mapOf(x to 6u, y to 4u) to Rational(544, 147) + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-5, 3), + mapOf(x to 2u) to Rational(35, 9), + mapOf(x to 3u) to Rational(-100, 27), + mapOf(x to 4u) to Rational(100, 81), + mapOf(y to 1u) to Rational(-5, 3), + mapOf(x to 1u, y to 1u) to Rational(14, 9), + mapOf(x to 2u, y to 1u) to Rational(1874, 189), + mapOf(x to 3u, y to 1u) to Rational(-620, 63), + mapOf(x to 4u, y to 1u) to Rational(40, 63), + mapOf(y to 2u) to Rational(16, 9), + mapOf(x to 1u, y to 2u) to Rational(365, 21), + mapOf(x to 2u, y to 2u) to Rational(112, 9), + mapOf(x to 3u, y to 2u) to Rational(-464, 63), + mapOf(x to 4u, y to 2u) to Rational(1996, 441), + mapOf(y to 3u) to Rational(10, 3), + mapOf(x to 1u, y to 3u) to Rational(118, 21), + mapOf(x to 2u, y to 3u) to Rational(-272, 21), + mapOf(x to 3u, y to 3u) to Rational(-764, 49), + mapOf(x to 4u, y to 3u) to Rational(8, 7), + mapOf(y to 4u) to Rational(1, 1), + mapOf(x to 1u, y to 4u) to Rational(-10, 7), + mapOf(x to 2u, y to 4u) to Rational(-171, 49), + mapOf(x to 3u, y to 4u) to Rational(20, 7), + mapOf(x to 4u, y to 4u) to Rational(4, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(18, 5), + mapOf(x to 1u) to Rational(-17, 5), + mapOf(x to 2u) to Rational(-2, 7), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(-5, 1), + mapOf(x to 2u, y to 1u) to Rational(-9, 1), + mapOf(y to 2u) to Rational(-8, 8), + mapOf(x to 1u, y to 2u) to Rational(2, 7), + mapOf(x to 2u, y to 2u) to Rational(-13, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-4, 8), + mapOf(x to 1u) to Rational(15, 9), + mapOf(x to 2u) to Rational(-10, 9), + mapOf(y to 1u) to Rational(5, 3), + mapOf(x to 1u, y to 1u) to Rational(4, 1), + mapOf(x to 2u, y to 1u) to Rational(-2, 7), + mapOf(y to 2u) to Rational(2, 2), + mapOf(x to 1u, y to 2u) to Rational(-5, 7), + mapOf(x to 2u, y to 2u) to Rational(-18, 9), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 9), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(10, 9), + mapOf(y to 1u) to Rational(13, 3), + mapOf(x to 1u, y to 1u) to Rational(-12, 4), + mapOf(x to 2u, y to 1u) to Rational(3, 6), + mapOf(y to 2u) to Rational(2, 9), + mapOf(x to 1u, y to 2u) to Rational(7, 3), + mapOf(x to 2u, y to 2u) to Rational(16, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 2), + mapOf(x to 1u) to Rational(6, 2), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 5), + mapOf(y to 2u) to Rational(8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(17, 4), + ) + ) + )), + "test 5'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(0, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ), + LabeledPolynomialAsIs(mapOf() to Rational(0, 1), + mapOf() to Rational(0, 1) + ) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(15, 7), + mapOf(x to 1u) to Rational(1, 5), + mapOf(x to 2u) to Rational(-7, 4), + mapOf(y to 1u) to Rational(-1, 9), + mapOf(x to 1u, y to 1u) to Rational(-2, 7), + mapOf(x to 2u, y to 1u) to Rational(17, 3), + mapOf(y to 2u) to Rational(2, 6), + mapOf(x to 1u, y to 2u) to Rational(-17, 6), + mapOf(x to 2u, y to 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 9), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(10, 9), + mapOf(y to 1u) to Rational(13, 3), + mapOf(x to 1u, y to 1u) to Rational(-12, 4), + mapOf(x to 2u, y to 1u) to Rational(3, 6), + mapOf(y to 2u) to Rational(2, 9), + mapOf(x to 1u, y to 2u) to Rational(7, 3), + mapOf(x to 2u, y to 2u) to Rational(16, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 2), + mapOf(x to 1u) to Rational(6, 2), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 5), + mapOf(y to 2u) to Rational(8, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(17, 4), + ) + ) + )), + "test 6'" + ) + } + @Test + fun test_RationalFunction_substitute_Double_Map() { + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs(emptyMap() to 0.0), + LabeledPolynomialAsIs(emptyMap() to 1.0), + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 1.0, + mapOf(x to 1u) to -2.0, + mapOf(x to 2u) to 1.0, + ), + LabeledPolynomialAsIs( + mapOf() to 1.0, + ) + ).substitute(mapOf( + x to 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf()), + 0.001, + "test 2" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + iota to 0.9211194782050933 + )), + 0.001, + "test 2'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 151.1502229133916, + mapOf(y to 1u) to -262.3790170577034, + mapOf(y to 2u) to 102.5097937392923, + ), + LabeledPolynomialAsIs( + mapOf() to -367.9969733169944, + mapOf(y to 1u) to 112.4911133334554, + mapOf(y to 2u) to -469.755906895345, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + x to -8.11707689492641, + )), + 0.001, + "test 3" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 151.1502229133916, + mapOf(y to 1u) to -262.3790170577034, + mapOf(y to 2u) to 102.5097937392923, + ), + LabeledPolynomialAsIs( + mapOf() to -367.9969733169944, + mapOf(y to 1u) to 112.4911133334554, + mapOf(y to 2u) to -469.755906895345, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + x to -8.11707689492641, + iota to 0.9211194782050933 + )), + 0.001, + "test 3'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 14.24074356896978, + mapOf(x to 1u) to -17.71987055153461, + mapOf(x to 2u) to -2.288056483312383, + ), + LabeledPolynomialAsIs( + mapOf() to 7.480604285873397, + mapOf(x to 1u) to -8.43478016688617, + mapOf(x to 2u) to -9.88934943900592, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + y to 0.795265651276015, + )), + 0.001, + "test 4" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 14.24074356896978, + mapOf(x to 1u) to -17.71987055153461, + mapOf(x to 2u) to -2.288056483312383, + ), + LabeledPolynomialAsIs( + mapOf() to 7.480604285873397, + mapOf(x to 1u) to -8.43478016688617, + mapOf(x to 2u) to -9.88934943900592, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + y to 0.795265651276015, + iota to 0.9211194782050933 + )), + 0.001, + "test 4'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 7.321261307532708, + ), + LabeledPolynomialAsIs( + mapOf() to -575.6325831127576, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + x to -8.11707689492641, + y to 0.795265651276015, + )), + 0.001, + "test 5" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 7.321261307532708, + ), + LabeledPolynomialAsIs( + mapOf() to -575.6325831127576, + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to 6.593754860231304, + mapOf(x to 1u) to -7.853302571550634, + mapOf(x to 2u) to 1.2265042281530025, + mapOf(y to 1u) to 3.762648877294904, + mapOf(x to 1u, y to 1u) to -8.945144619305292, + mapOf(x to 2u, y to 1u) to -5.141384718042281, + mapOf(y to 2u) to 7.359794483988782, + mapOf(x to 1u, y to 2u) to -4.3526172680518815, + mapOf(x to 2u, y to 2u) to 0.907910924854372, + ), + LabeledPolynomialAsIs( + mapOf() to 9.533292132172562, + mapOf(x to 1u) to -1.982814534018857, + mapOf(x to 2u) to -5.974248303415283, + mapOf(y to 1u) to 1.5876716499288879, + mapOf(x to 1u, y to 1u) to -7.535152566659664, + mapOf(x to 2u, y to 1u) to 0.7549300500153517, + mapOf(y to 2u) to -5.242030058021028, + mapOf(x to 1u, y to 2u) to -0.7265704289690582, + mapOf(x to 2u, y to 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + x to -8.11707689492641, + y to 0.795265651276015, + iota to 0.9211194782050933 + )), + 0.001, + "test 5'" + ) + } + @Test + fun test_RationalFunction_substitute_Constant_Map() { + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ).substitute(RationalField, mapOf( + x to Rational(1) + )), + "test 1" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(22047, 2450), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-2204953, 147000), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + x to Rational(7, 5), + y to Rational(-13, 7), + )), + "test 2" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(22047, 2450), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-2204953, 147000), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + x to Rational(7, 5), + y to Rational(-13, 7), + iota to Rational(-16, 4), + )), + "test 2'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(4191, 490), + mapOf(x to 1u) to Rational(14975, 1176), + mapOf(x to 2u) to Rational(-10429, 1176) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-775, 147), + mapOf(x to 1u) to Rational(-155, 49), + mapOf(x to 2u) to Rational(-757, 280) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + y to Rational(-13, 7), + )), + "test 3" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(4191, 490), + mapOf(x to 1u) to Rational(14975, 1176), + mapOf(x to 2u) to Rational(-10429, 1176) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-775, 147), + mapOf(x to 1u) to Rational(-155, 49), + mapOf(x to 2u) to Rational(-757, 280) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + y to Rational(-13, 7), + iota to Rational(-16, 4), + )), + "test 3'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-939, 200), + mapOf(y to 1u) to Rational(123, 50), + mapOf(y to 2u) to Rational(1059, 200) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(121, 25), + mapOf(y to 1u) to Rational(-949, 375), + mapOf(y to 2u) to Rational(-1423, 200) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + x to Rational(7, 5), + )), + "test 4" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-939, 200), + mapOf(y to 1u) to Rational(123, 50), + mapOf(y to 2u) to Rational(1059, 200) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(121, 25), + mapOf(y to 1u) to Rational(-949, 375), + mapOf(y to 2u) to Rational(-1423, 200) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + x to Rational(7, 5), + iota to Rational(-16, 4), + )), + "test 4'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf()), + "test 5" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-3, 5), + mapOf(x to 1u) to Rational(-18, 4), + mapOf(x to 2u) to Rational(9, 8), + mapOf(y to 1u) to Rational(-11, 6), + mapOf(x to 1u, y to 1u) to Rational(-16, 3), + mapOf(x to 2u, y to 1u) to Rational(12, 2), + mapOf(y to 2u) to Rational(5, 3), + mapOf(x to 1u, y to 2u) to Rational(17, 8), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(11, 1), + mapOf(x to 1u) to Rational(4, 1), + mapOf(x to 2u) to Rational(-18, 3), + mapOf(y to 1u) to Rational(12, 9), + mapOf(x to 1u, y to 1u) to Rational(14, 7), + mapOf(x to 2u, y to 1u) to Rational(-17, 5), + mapOf(y to 2u) to Rational(-4, 1), + mapOf(x to 1u, y to 2u) to Rational(-5, 5), + mapOf(x to 2u, y to 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + iota to Rational(-16, 4), + )), + "test 5'" + ) + } + @Test + fun test_RationalFunction_substitute_Polynomial_Map() { + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + )), + "test 1" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(211, 4), + mapOf(x to 2u) to Rational(88, 3), + mapOf(x to 3u) to Rational(-63, 8), + mapOf(x to 4u) to Rational(441, 16), + mapOf(y to 1u) to Rational(-671, 15), + mapOf(x to 1u, y to 1u) to Rational(-551, 21), + mapOf(x to 2u, y to 1u) to Rational(279, 25), + mapOf(x to 3u, y to 1u) to Rational(231, 20), + mapOf(y to 2u) to Rational(-1436, 1575), + mapOf(x to 1u, y to 2u) to Rational(2471, 250), + mapOf(x to 2u, y to 2u) to Rational(-4919, 100), + mapOf(y to 3u) to Rational(-1464, 125), + mapOf(x to 1u, y to 3u) to Rational(-264, 25), + mapOf(y to 4u) to Rational(576, 25), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(-9, 4), + mapOf(x to 2u) to Rational(943, 8), + mapOf(x to 3u) to Rational(117, 8), + mapOf(x to 4u) to Rational(147, 16), + mapOf(y to 1u) to Rational(289, 90), + mapOf(x to 1u, y to 1u) to Rational(-2692, 15), + mapOf(x to 2u, y to 1u) to Rational(-1629, 140), + mapOf(x to 3u, y to 1u) to Rational(77, 20), + mapOf(y to 2u) to Rational(6187, 75), + mapOf(x to 1u, y to 2u) to Rational(-2879, 175), + mapOf(x to 2u, y to 2u) to Rational(-4919, 300), + mapOf(y to 3u) to Rational(336, 25), + mapOf(x to 1u, y to 3u) to Rational(-88, 25), + mapOf(y to 4u) to Rational(192, 25), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(3, 2), + mapOf(y to 1u) to Rational(8, 5), + ), + y to LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(7, 2), + mapOf(y to 1u) to Rational(-3, 1), + ) + )), + "test 2" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1202861, 210), + mapOf(x to 1u) to Rational(-215117, 45), + mapOf(x to 2u) to Rational(10889651, 19845), + mapOf(x to 3u) to Rational(-3503956, 6615), + mapOf(x to 4u) to Rational(809066, 2205), + mapOf(x to 5u) to Rational(-9056, 735), + mapOf(x to 6u) to Rational(5396, 315), + mapOf(x to 7u) to Rational(-752, 147), + mapOf(x to 8u) to Rational(16, 49), + mapOf(y to 1u) to Rational(1738469, 1470), + mapOf(x to 1u, y to 1u) to Rational(-926238703, 52920), + mapOf(x to 2u, y to 1u) to Rational(-44113982, 6615), + mapOf(x to 3u, y to 1u) to Rational(10423519, 5292), + mapOf(x to 4u, y to 1u) to Rational(3769712, 2205), + mapOf(x to 5u, y to 1u) to Rational(8905046, 6615), + mapOf(x to 6u, y to 1u) to Rational(1186972, 6615), + mapOf(x to 7u, y to 1u) to Rational(22124, 441), + mapOf(x to 8u, y to 1u) to Rational(-1504, 147), + mapOf(y to 2u) to Rational(-54723628, 2205), + mapOf(x to 1u, y to 2u) to Rational(70109407, 1323), + mapOf(x to 2u, y to 2u) to Rational(151072591, 17640), + mapOf(x to 3u, y to 2u) to Rational(1216428107, 52920), + mapOf(x to 4u, y to 2u) to Rational(2587873193, 317520), + mapOf(x to 5u, y to 2u) to Rational(393536369, 79380), + mapOf(x to 6u, y to 2u) to Rational(137614937, 79380), + mapOf(x to 7u, y to 2u) to Rational(566866, 1323), + mapOf(x to 8u, y to 2u) to Rational(41848, 441), + mapOf(y to 3u) to Rational(-19470406, 2205), + mapOf(x to 1u, y to 3u) to Rational(72514195, 882), + mapOf(x to 2u, y to 3u) to Rational(-78090707, 1764), + mapOf(x to 3u, y to 3u) to Rational(-1988237707, 26460), + mapOf(x to 4u, y to 3u) to Rational(-802137919, 17640), + mapOf(x to 5u, y to 3u) to Rational(-139989463, 5880), + mapOf(x to 6u, y to 3u) to Rational(-26066641, 3780), + mapOf(x to 7u, y to 3u) to Rational(-2363369, 1323), + mapOf(x to 8u, y to 3u) to Rational(-108280, 441), + mapOf(y to 4u) to Rational(14878516, 441), + mapOf(x to 1u, y to 4u) to Rational(-253416724, 2205), + mapOf(x to 2u, y to 4u) to Rational(16699157, 840), + mapOf(x to 3u, y to 4u) to Rational(-105220979, 13230), + mapOf(x to 4u, y to 4u) to Rational(208266383, 5880), + mapOf(x to 5u, y to 4u) to Rational(650135309, 26460), + mapOf(x to 6u, y to 4u) to Rational(123808663, 11760), + mapOf(x to 7u, y to 4u) to Rational(8563385, 2646), + mapOf(x to 8u, y to 4u) to Rational(19721, 49), + mapOf(y to 5u) to Rational(675645, 49), + mapOf(x to 1u, y to 5u) to Rational(-70554077, 588), + mapOf(x to 2u, y to 5u) to Rational(157884029, 980), + mapOf(x to 3u, y to 5u) to Rational(489548623, 4410), + mapOf(x to 4u, y to 5u) to Rational(148540519, 17640), + mapOf(x to 5u, y to 5u) to Rational(-5559551, 392), + mapOf(x to 6u, y to 5u) to Rational(-18335711, 1470), + mapOf(x to 7u, y to 5u) to Rational(-38437, 9), + mapOf(x to 8u, y to 5u) to Rational(-29620, 63), + mapOf(y to 6u) to Rational(-727625, 49), + mapOf(x to 1u, y to 6u) to Rational(7046685, 98), + mapOf(x to 2u, y to 6u) to Rational(-334814231, 7056), + mapOf(x to 3u, y to 6u) to Rational(-243971737, 17640), + mapOf(x to 4u, y to 6u) to Rational(-571116659, 35280), + mapOf(x to 5u, y to 6u) to Rational(567538, 315), + mapOf(x to 6u, y to 6u) to Rational(3199768, 315), + mapOf(x to 7u, y to 6u) to Rational(227744, 63), + mapOf(x to 8u, y to 6u) to Rational(23116, 63), + mapOf(y to 7u) to Rational(-27500, 7), + mapOf(x to 1u, y to 7u) to Rational(120125, 3), + mapOf(x to 2u, y to 7u) to Rational(-279200, 3), + mapOf(x to 3u, y to 7u) to Rational(-100160, 7), + mapOf(x to 4u, y to 7u) to Rational(920452, 21), + mapOf(x to 5u, y to 7u) to Rational(226481, 21), + mapOf(x to 6u, y to 7u) to Rational(-34428, 7), + mapOf(x to 7u, y to 7u) to Rational(-6232, 3), + mapOf(x to 8u, y to 7u) to Rational(-608, 3), + mapOf(y to 8u) to Rational(2500, 1), + mapOf(x to 1u, y to 8u) to Rational(-19000, 1), + mapOf(x to 2u, y to 8u) to Rational(37900, 1), + mapOf(x to 3u, y to 8u) to Rational(-1840, 1), + mapOf(x to 4u, y to 8u) to Rational(-17876, 1), + mapOf(x to 5u, y to 8u) to Rational(-1240, 1), + mapOf(x to 6u, y to 8u) to Rational(2788, 1), + mapOf(x to 7u, y to 8u) to Rational(800, 1), + mapOf(x to 8u, y to 8u) to Rational(64, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(162487, 63), + mapOf(x to 1u) to Rational(-92713, 54), + mapOf(x to 2u) to Rational(802436, 1323), + mapOf(x to 3u) to Rational(-55088, 441), + mapOf(x to 4u) to Rational(1404034, 9261), + mapOf(x to 5u) to Rational(-5804, 1029), + mapOf(x to 6u) to Rational(51556, 9261), + mapOf(x to 7u) to Rational(-752, 441), + mapOf(x to 8u) to Rational(16, 147), + mapOf(y to 1u) to Rational(296071, 441), + mapOf(x to 1u, y to 1u) to Rational(-4991281, 882), + mapOf(x to 2u, y to 1u) to Rational(-18702811, 9261), + mapOf(x to 3u, y to 1u) to Rational(40759043, 27783), + mapOf(x to 4u, y to 1u) to Rational(19768501, 27783), + mapOf(x to 5u, y to 1u) to Rational(14307337, 27783), + mapOf(x to 6u, y to 1u) to Rational(1655684, 27783), + mapOf(x to 7u, y to 1u) to Rational(22124, 1323), + mapOf(x to 8u, y to 1u) to Rational(-1504, 441), + mapOf(y to 2u) to Rational(-27667474, 3087), + mapOf(x to 1u, y to 2u) to Rational(265605901, 12348), + mapOf(x to 2u, y to 2u) to Rational(160360775, 98784), + mapOf(x to 3u, y to 2u) to Rational(1169992093, 148176), + mapOf(x to 4u, y to 2u) to Rational(3978014077, 1333584), + mapOf(x to 5u, y to 2u) to Rational(567058123, 333396), + mapOf(x to 6u, y to 2u) to Rational(205132579, 333396), + mapOf(x to 7u, y to 2u) to Rational(566866, 3969), + mapOf(x to 8u, y to 2u) to Rational(41848, 1323), + mapOf(y to 3u) to Rational(-2228822, 1029), + mapOf(x to 1u, y to 3u) to Rational(80179390, 3087), + mapOf(x to 2u, y to 3u) to Rational(-1378630487, 74088), + mapOf(x to 3u, y to 3u) to Rational(-3385811693, 111132), + mapOf(x to 4u, y to 3u) to Rational(-820686977, 49392), + mapOf(x to 5u, y to 3u) to Rational(-89101027, 10584), + mapOf(x to 6u, y to 3u) to Rational(-37847387, 15876), + mapOf(x to 7u, y to 3u) to Rational(-2363369, 3969), + mapOf(x to 8u, y to 3u) to Rational(-108280, 1323), + mapOf(y to 4u) to Rational(12619982, 1029), + mapOf(x to 1u, y to 4u) to Rational(-277723177, 6174), + mapOf(x to 2u, y to 4u) to Rational(649414169, 49392), + mapOf(x to 3u, y to 4u) to Rational(14457595, 63504), + mapOf(x to 4u, y to 4u) to Rational(139270339, 10584), + mapOf(x to 5u, y to 4u) to Rational(140367961, 15876), + mapOf(x to 6u, y to 4u) to Rational(25467083, 7056), + mapOf(x to 7u, y to 4u) to Rational(8563385, 7938), + mapOf(x to 8u, y to 4u) to Rational(19721, 147), + mapOf(y to 5u) to Rational(643850, 147), + mapOf(x to 1u, y to 5u) to Rational(-11818025, 294), + mapOf(x to 2u, y to 5u) to Rational(33963203, 588), + mapOf(x to 3u, y to 5u) to Rational(207216235, 5292), + mapOf(x to 4u, y to 5u) to Rational(2861021, 1512), + mapOf(x to 5u, y to 5u) to Rational(-6302335, 1176), + mapOf(x to 6u, y to 5u) to Rational(-3738587, 882), + mapOf(x to 7u, y to 5u) to Rational(-38437, 27), + mapOf(x to 8u, y to 5u) to Rational(-29620, 189), + mapOf(y to 6u) to Rational(-248725, 49), + mapOf(x to 1u, y to 6u) to Rational(2478535, 98), + mapOf(x to 2u, y to 6u) to Rational(-399721367, 21168), + mapOf(x to 3u, y to 6u) to Rational(-54309317, 10584), + mapOf(x to 4u, y to 6u) to Rational(-95398327, 21168), + mapOf(x to 5u, y to 6u) to Rational(173750, 189), + mapOf(x to 6u, y to 6u) to Rational(92216, 27), + mapOf(x to 7u, y to 6u) to Rational(227744, 189), + mapOf(x to 8u, y to 6u) to Rational(23116, 189), + mapOf(y to 7u) to Rational(-27500, 21), + mapOf(x to 1u, y to 7u) to Rational(120125, 9), + mapOf(x to 2u, y to 7u) to Rational(-279200, 9), + mapOf(x to 3u, y to 7u) to Rational(-100160, 21), + mapOf(x to 4u, y to 7u) to Rational(920452, 63), + mapOf(x to 5u, y to 7u) to Rational(226481, 63), + mapOf(x to 6u, y to 7u) to Rational(-11476, 7), + mapOf(x to 7u, y to 7u) to Rational(-6232, 9), + mapOf(x to 8u, y to 7u) to Rational(-608, 9), + mapOf(y to 8u) to Rational(2500, 3), + mapOf(x to 1u, y to 8u) to Rational(-19000, 3), + mapOf(x to 2u, y to 8u) to Rational(37900, 3), + mapOf(x to 3u, y to 8u) to Rational(-1840, 3), + mapOf(x to 4u, y to 8u) to Rational(-17876, 3), + mapOf(x to 5u, y to 8u) to Rational(-1240, 3), + mapOf(x to 6u, y to 8u) to Rational(2788, 3), + mapOf(x to 7u, y to 8u) to Rational(800, 3), + mapOf(x to 8u, y to 8u) to Rational(64, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(18, 1), + mapOf(x to 1u) to Rational(16, 3), + mapOf(x to 2u) to Rational(12, 6), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 4), + mapOf(x to 2u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(-10, 1), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + y to LabeledPolynomialAsIs( + mapOf() to Rational(8, 2), + mapOf(x to 1u) to Rational(-15, 5), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 7), + mapOf(x to 1u, y to 1u) to Rational(-16, 6), + mapOf(x to 2u, y to 1u) to Rational(-13, 3), + mapOf(y to 2u) to Rational(-5, 1), + mapOf(x to 1u, y to 2u) to Rational(17, 1), + mapOf(x to 2u, y to 2u) to Rational(8, 2), + ), + )), + "test 3" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1202861, 210), + mapOf(x to 1u) to Rational(-215117, 45), + mapOf(x to 2u) to Rational(10889651, 19845), + mapOf(x to 3u) to Rational(-3503956, 6615), + mapOf(x to 4u) to Rational(809066, 2205), + mapOf(x to 5u) to Rational(-9056, 735), + mapOf(x to 6u) to Rational(5396, 315), + mapOf(x to 7u) to Rational(-752, 147), + mapOf(x to 8u) to Rational(16, 49), + mapOf(y to 1u) to Rational(1738469, 1470), + mapOf(x to 1u, y to 1u) to Rational(-926238703, 52920), + mapOf(x to 2u, y to 1u) to Rational(-44113982, 6615), + mapOf(x to 3u, y to 1u) to Rational(10423519, 5292), + mapOf(x to 4u, y to 1u) to Rational(3769712, 2205), + mapOf(x to 5u, y to 1u) to Rational(8905046, 6615), + mapOf(x to 6u, y to 1u) to Rational(1186972, 6615), + mapOf(x to 7u, y to 1u) to Rational(22124, 441), + mapOf(x to 8u, y to 1u) to Rational(-1504, 147), + mapOf(y to 2u) to Rational(-54723628, 2205), + mapOf(x to 1u, y to 2u) to Rational(70109407, 1323), + mapOf(x to 2u, y to 2u) to Rational(151072591, 17640), + mapOf(x to 3u, y to 2u) to Rational(1216428107, 52920), + mapOf(x to 4u, y to 2u) to Rational(2587873193, 317520), + mapOf(x to 5u, y to 2u) to Rational(393536369, 79380), + mapOf(x to 6u, y to 2u) to Rational(137614937, 79380), + mapOf(x to 7u, y to 2u) to Rational(566866, 1323), + mapOf(x to 8u, y to 2u) to Rational(41848, 441), + mapOf(y to 3u) to Rational(-19470406, 2205), + mapOf(x to 1u, y to 3u) to Rational(72514195, 882), + mapOf(x to 2u, y to 3u) to Rational(-78090707, 1764), + mapOf(x to 3u, y to 3u) to Rational(-1988237707, 26460), + mapOf(x to 4u, y to 3u) to Rational(-802137919, 17640), + mapOf(x to 5u, y to 3u) to Rational(-139989463, 5880), + mapOf(x to 6u, y to 3u) to Rational(-26066641, 3780), + mapOf(x to 7u, y to 3u) to Rational(-2363369, 1323), + mapOf(x to 8u, y to 3u) to Rational(-108280, 441), + mapOf(y to 4u) to Rational(14878516, 441), + mapOf(x to 1u, y to 4u) to Rational(-253416724, 2205), + mapOf(x to 2u, y to 4u) to Rational(16699157, 840), + mapOf(x to 3u, y to 4u) to Rational(-105220979, 13230), + mapOf(x to 4u, y to 4u) to Rational(208266383, 5880), + mapOf(x to 5u, y to 4u) to Rational(650135309, 26460), + mapOf(x to 6u, y to 4u) to Rational(123808663, 11760), + mapOf(x to 7u, y to 4u) to Rational(8563385, 2646), + mapOf(x to 8u, y to 4u) to Rational(19721, 49), + mapOf(y to 5u) to Rational(675645, 49), + mapOf(x to 1u, y to 5u) to Rational(-70554077, 588), + mapOf(x to 2u, y to 5u) to Rational(157884029, 980), + mapOf(x to 3u, y to 5u) to Rational(489548623, 4410), + mapOf(x to 4u, y to 5u) to Rational(148540519, 17640), + mapOf(x to 5u, y to 5u) to Rational(-5559551, 392), + mapOf(x to 6u, y to 5u) to Rational(-18335711, 1470), + mapOf(x to 7u, y to 5u) to Rational(-38437, 9), + mapOf(x to 8u, y to 5u) to Rational(-29620, 63), + mapOf(y to 6u) to Rational(-727625, 49), + mapOf(x to 1u, y to 6u) to Rational(7046685, 98), + mapOf(x to 2u, y to 6u) to Rational(-334814231, 7056), + mapOf(x to 3u, y to 6u) to Rational(-243971737, 17640), + mapOf(x to 4u, y to 6u) to Rational(-571116659, 35280), + mapOf(x to 5u, y to 6u) to Rational(567538, 315), + mapOf(x to 6u, y to 6u) to Rational(3199768, 315), + mapOf(x to 7u, y to 6u) to Rational(227744, 63), + mapOf(x to 8u, y to 6u) to Rational(23116, 63), + mapOf(y to 7u) to Rational(-27500, 7), + mapOf(x to 1u, y to 7u) to Rational(120125, 3), + mapOf(x to 2u, y to 7u) to Rational(-279200, 3), + mapOf(x to 3u, y to 7u) to Rational(-100160, 7), + mapOf(x to 4u, y to 7u) to Rational(920452, 21), + mapOf(x to 5u, y to 7u) to Rational(226481, 21), + mapOf(x to 6u, y to 7u) to Rational(-34428, 7), + mapOf(x to 7u, y to 7u) to Rational(-6232, 3), + mapOf(x to 8u, y to 7u) to Rational(-608, 3), + mapOf(y to 8u) to Rational(2500, 1), + mapOf(x to 1u, y to 8u) to Rational(-19000, 1), + mapOf(x to 2u, y to 8u) to Rational(37900, 1), + mapOf(x to 3u, y to 8u) to Rational(-1840, 1), + mapOf(x to 4u, y to 8u) to Rational(-17876, 1), + mapOf(x to 5u, y to 8u) to Rational(-1240, 1), + mapOf(x to 6u, y to 8u) to Rational(2788, 1), + mapOf(x to 7u, y to 8u) to Rational(800, 1), + mapOf(x to 8u, y to 8u) to Rational(64, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(162487, 63), + mapOf(x to 1u) to Rational(-92713, 54), + mapOf(x to 2u) to Rational(802436, 1323), + mapOf(x to 3u) to Rational(-55088, 441), + mapOf(x to 4u) to Rational(1404034, 9261), + mapOf(x to 5u) to Rational(-5804, 1029), + mapOf(x to 6u) to Rational(51556, 9261), + mapOf(x to 7u) to Rational(-752, 441), + mapOf(x to 8u) to Rational(16, 147), + mapOf(y to 1u) to Rational(296071, 441), + mapOf(x to 1u, y to 1u) to Rational(-4991281, 882), + mapOf(x to 2u, y to 1u) to Rational(-18702811, 9261), + mapOf(x to 3u, y to 1u) to Rational(40759043, 27783), + mapOf(x to 4u, y to 1u) to Rational(19768501, 27783), + mapOf(x to 5u, y to 1u) to Rational(14307337, 27783), + mapOf(x to 6u, y to 1u) to Rational(1655684, 27783), + mapOf(x to 7u, y to 1u) to Rational(22124, 1323), + mapOf(x to 8u, y to 1u) to Rational(-1504, 441), + mapOf(y to 2u) to Rational(-27667474, 3087), + mapOf(x to 1u, y to 2u) to Rational(265605901, 12348), + mapOf(x to 2u, y to 2u) to Rational(160360775, 98784), + mapOf(x to 3u, y to 2u) to Rational(1169992093, 148176), + mapOf(x to 4u, y to 2u) to Rational(3978014077, 1333584), + mapOf(x to 5u, y to 2u) to Rational(567058123, 333396), + mapOf(x to 6u, y to 2u) to Rational(205132579, 333396), + mapOf(x to 7u, y to 2u) to Rational(566866, 3969), + mapOf(x to 8u, y to 2u) to Rational(41848, 1323), + mapOf(y to 3u) to Rational(-2228822, 1029), + mapOf(x to 1u, y to 3u) to Rational(80179390, 3087), + mapOf(x to 2u, y to 3u) to Rational(-1378630487, 74088), + mapOf(x to 3u, y to 3u) to Rational(-3385811693, 111132), + mapOf(x to 4u, y to 3u) to Rational(-820686977, 49392), + mapOf(x to 5u, y to 3u) to Rational(-89101027, 10584), + mapOf(x to 6u, y to 3u) to Rational(-37847387, 15876), + mapOf(x to 7u, y to 3u) to Rational(-2363369, 3969), + mapOf(x to 8u, y to 3u) to Rational(-108280, 1323), + mapOf(y to 4u) to Rational(12619982, 1029), + mapOf(x to 1u, y to 4u) to Rational(-277723177, 6174), + mapOf(x to 2u, y to 4u) to Rational(649414169, 49392), + mapOf(x to 3u, y to 4u) to Rational(14457595, 63504), + mapOf(x to 4u, y to 4u) to Rational(139270339, 10584), + mapOf(x to 5u, y to 4u) to Rational(140367961, 15876), + mapOf(x to 6u, y to 4u) to Rational(25467083, 7056), + mapOf(x to 7u, y to 4u) to Rational(8563385, 7938), + mapOf(x to 8u, y to 4u) to Rational(19721, 147), + mapOf(y to 5u) to Rational(643850, 147), + mapOf(x to 1u, y to 5u) to Rational(-11818025, 294), + mapOf(x to 2u, y to 5u) to Rational(33963203, 588), + mapOf(x to 3u, y to 5u) to Rational(207216235, 5292), + mapOf(x to 4u, y to 5u) to Rational(2861021, 1512), + mapOf(x to 5u, y to 5u) to Rational(-6302335, 1176), + mapOf(x to 6u, y to 5u) to Rational(-3738587, 882), + mapOf(x to 7u, y to 5u) to Rational(-38437, 27), + mapOf(x to 8u, y to 5u) to Rational(-29620, 189), + mapOf(y to 6u) to Rational(-248725, 49), + mapOf(x to 1u, y to 6u) to Rational(2478535, 98), + mapOf(x to 2u, y to 6u) to Rational(-399721367, 21168), + mapOf(x to 3u, y to 6u) to Rational(-54309317, 10584), + mapOf(x to 4u, y to 6u) to Rational(-95398327, 21168), + mapOf(x to 5u, y to 6u) to Rational(173750, 189), + mapOf(x to 6u, y to 6u) to Rational(92216, 27), + mapOf(x to 7u, y to 6u) to Rational(227744, 189), + mapOf(x to 8u, y to 6u) to Rational(23116, 189), + mapOf(y to 7u) to Rational(-27500, 21), + mapOf(x to 1u, y to 7u) to Rational(120125, 9), + mapOf(x to 2u, y to 7u) to Rational(-279200, 9), + mapOf(x to 3u, y to 7u) to Rational(-100160, 21), + mapOf(x to 4u, y to 7u) to Rational(920452, 63), + mapOf(x to 5u, y to 7u) to Rational(226481, 63), + mapOf(x to 6u, y to 7u) to Rational(-11476, 7), + mapOf(x to 7u, y to 7u) to Rational(-6232, 9), + mapOf(x to 8u, y to 7u) to Rational(-608, 9), + mapOf(y to 8u) to Rational(2500, 3), + mapOf(x to 1u, y to 8u) to Rational(-19000, 3), + mapOf(x to 2u, y to 8u) to Rational(37900, 3), + mapOf(x to 3u, y to 8u) to Rational(-1840, 3), + mapOf(x to 4u, y to 8u) to Rational(-17876, 3), + mapOf(x to 5u, y to 8u) to Rational(-1240, 3), + mapOf(x to 6u, y to 8u) to Rational(2788, 3), + mapOf(x to 7u, y to 8u) to Rational(800, 3), + mapOf(x to 8u, y to 8u) to Rational(64, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(18, 1), + mapOf(x to 1u) to Rational(16, 3), + mapOf(x to 2u) to Rational(12, 6), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 4), + mapOf(x to 2u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(-10, 1), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + y to LabeledPolynomialAsIs( + mapOf() to Rational(8, 2), + mapOf(x to 1u) to Rational(-15, 5), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 7), + mapOf(x to 1u, y to 1u) to Rational(-16, 6), + mapOf(x to 2u, y to 1u) to Rational(-13, 3), + mapOf(y to 2u) to Rational(-5, 1), + mapOf(x to 1u, y to 2u) to Rational(17, 1), + mapOf(x to 2u, y to 2u) to Rational(8, 2), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-6, 1), + mapOf(x to 1u) to Rational(-9, 8), + mapOf(x to 2u) to Rational(17, 5), + mapOf(y to 1u) to Rational(-2, 3), + mapOf(x to 1u, y to 1u) to Rational(1, 5), + mapOf(x to 2u, y to 1u) to Rational(-11, 7), + mapOf(y to 2u) to Rational(13, 6), + mapOf(x to 1u, y to 2u) to Rational(-15, 2), + mapOf(x to 2u, y to 2u) to Rational(-14, 4), + ) + )), + "test 3'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(493, 6), + mapOf(x to 1u) to Rational(-15991, 210), + mapOf(x to 2u) to Rational(2734, 63), + mapOf(x to 3u) to Rational(-8213, 245), + mapOf(x to 4u) to Rational(1843, 147), + mapOf(x to 5u) to Rational(-432, 245), + mapOf(x to 6u) to Rational(4, 49), + mapOf(y to 1u) to Rational(-66, 1), + mapOf(x to 1u, y to 1u) to Rational(-92924, 2205), + mapOf(x to 2u, y to 1u) to Rational(-257461, 2205), + mapOf(x to 3u, y to 1u) to Rational(58658, 2205), + mapOf(x to 4u, y to 1u) to Rational(-87884, 2205), + mapOf(x to 5u, y to 1u) to Rational(2726, 105), + mapOf(x to 6u, y to 1u) to Rational(-52, 21), + mapOf(y to 2u) to Rational(-17569, 147), + mapOf(x to 1u, y to 2u) to Rational(368819, 735), + mapOf(x to 2u, y to 2u) to Rational(-644626, 6615), + mapOf(x to 3u, y to 2u) to Rational(221738, 945), + mapOf(x to 4u, y to 2u) to Rational(-18022, 945), + mapOf(x to 5u, y to 2u) to Rational(-1201, 315), + mapOf(x to 6u, y to 2u) to Rational(1327, 63), + mapOf(y to 3u) to Rational(240, 7), + mapOf(x to 1u, y to 3u) to Rational(-868, 9), + mapOf(x to 2u, y to 3u) to Rational(-8936, 315), + mapOf(x to 3u, y to 3u) to Rational(-77146, 315), + mapOf(x to 4u, y to 3u) to Rational(-4072, 315), + mapOf(x to 5u, y to 3u) to Rational(-2218, 15), + mapOf(x to 6u, y to 3u) to Rational(-104, 3), + mapOf(y to 4u) to Rational(100, 3), + mapOf(x to 1u, y to 4u) to Rational(-725, 3), + mapOf(x to 2u, y to 4u) to Rational(459, 1), + mapOf(x to 3u, y to 4u) to Rational(-2071, 15), + mapOf(x to 4u, y to 4u) to Rational(2831, 15), + mapOf(x to 5u, y to 4u) to Rational(632, 5), + mapOf(x to 6u, y to 4u) to Rational(16, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1255, 9), + mapOf(x to 1u) to Rational(-24781, 126), + mapOf(x to 2u) to Rational(1195, 14), + mapOf(x to 3u) to Rational(-1931, 147), + mapOf(x to 4u) to Rational(439, 147), + mapOf(x to 5u) to Rational(-172, 343), + mapOf(x to 6u) to Rational(4, 147), + mapOf(y to 1u) to Rational(-183, 1), + mapOf(x to 1u, y to 1u) to Rational(-30988, 441), + mapOf(x to 2u, y to 1u) to Rational(-56137, 294), + mapOf(x to 3u, y to 1u) to Rational(204308, 1029), + mapOf(x to 4u, y to 1u) to Rational(-3263, 441), + mapOf(x to 5u, y to 1u) to Rational(2662, 441), + mapOf(x to 6u, y to 1u) to Rational(-52, 63), + mapOf(y to 2u) to Rational(-87119, 294), + mapOf(x to 1u, y to 2u) to Rational(1077919, 686), + mapOf(x to 2u, y to 2u) to Rational(-35209, 147), + mapOf(x to 3u, y to 2u) to Rational(15041, 147), + mapOf(x to 4u, y to 2u) to Rational(240889, 1323), + mapOf(x to 5u, y to 2u) to Rational(27778, 1323), + mapOf(x to 6u, y to 2u) to Rational(1327, 189), + mapOf(y to 3u) to Rational(1620, 7), + mapOf(x to 1u, y to 3u) to Rational(-25716, 49), + mapOf(x to 2u, y to 3u) to Rational(-32078, 49), + mapOf(x to 3u, y to 3u) to Rational(-704038, 441), + mapOf(x to 4u, y to 3u) to Rational(-30190, 63), + mapOf(x to 5u, y to 3u) to Rational(-5414, 63), + mapOf(x to 6u, y to 3u) to Rational(-104, 9), + mapOf(y to 4u) to Rational(225, 1), + mapOf(x to 1u, y to 4u) to Rational(-10560, 7), + mapOf(x to 2u, y to 4u) to Rational(44176, 21), + mapOf(x to 3u, y to 4u) to Rational(28996, 21), + mapOf(x to 4u, y to 4u) to Rational(2405, 7), + mapOf(x to 5u, y to 4u) to Rational(1240, 21), + mapOf(x to 6u, y to 4u) to Rational(16, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + y to LabeledPolynomialAsIs( + mapOf() to Rational(8, 2), + mapOf(x to 1u) to Rational(-15, 5), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 7), + mapOf(x to 1u, y to 1u) to Rational(-16, 6), + mapOf(x to 2u, y to 1u) to Rational(-13, 3), + mapOf(y to 2u) to Rational(-5, 1), + mapOf(x to 1u, y to 2u) to Rational(17, 1), + mapOf(x to 2u, y to 2u) to Rational(8, 2), + ), + )), + "test 4" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(493, 6), + mapOf(x to 1u) to Rational(-15991, 210), + mapOf(x to 2u) to Rational(2734, 63), + mapOf(x to 3u) to Rational(-8213, 245), + mapOf(x to 4u) to Rational(1843, 147), + mapOf(x to 5u) to Rational(-432, 245), + mapOf(x to 6u) to Rational(4, 49), + mapOf(y to 1u) to Rational(-66, 1), + mapOf(x to 1u, y to 1u) to Rational(-92924, 2205), + mapOf(x to 2u, y to 1u) to Rational(-257461, 2205), + mapOf(x to 3u, y to 1u) to Rational(58658, 2205), + mapOf(x to 4u, y to 1u) to Rational(-87884, 2205), + mapOf(x to 5u, y to 1u) to Rational(2726, 105), + mapOf(x to 6u, y to 1u) to Rational(-52, 21), + mapOf(y to 2u) to Rational(-17569, 147), + mapOf(x to 1u, y to 2u) to Rational(368819, 735), + mapOf(x to 2u, y to 2u) to Rational(-644626, 6615), + mapOf(x to 3u, y to 2u) to Rational(221738, 945), + mapOf(x to 4u, y to 2u) to Rational(-18022, 945), + mapOf(x to 5u, y to 2u) to Rational(-1201, 315), + mapOf(x to 6u, y to 2u) to Rational(1327, 63), + mapOf(y to 3u) to Rational(240, 7), + mapOf(x to 1u, y to 3u) to Rational(-868, 9), + mapOf(x to 2u, y to 3u) to Rational(-8936, 315), + mapOf(x to 3u, y to 3u) to Rational(-77146, 315), + mapOf(x to 4u, y to 3u) to Rational(-4072, 315), + mapOf(x to 5u, y to 3u) to Rational(-2218, 15), + mapOf(x to 6u, y to 3u) to Rational(-104, 3), + mapOf(y to 4u) to Rational(100, 3), + mapOf(x to 1u, y to 4u) to Rational(-725, 3), + mapOf(x to 2u, y to 4u) to Rational(459, 1), + mapOf(x to 3u, y to 4u) to Rational(-2071, 15), + mapOf(x to 4u, y to 4u) to Rational(2831, 15), + mapOf(x to 5u, y to 4u) to Rational(632, 5), + mapOf(x to 6u, y to 4u) to Rational(16, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1255, 9), + mapOf(x to 1u) to Rational(-24781, 126), + mapOf(x to 2u) to Rational(1195, 14), + mapOf(x to 3u) to Rational(-1931, 147), + mapOf(x to 4u) to Rational(439, 147), + mapOf(x to 5u) to Rational(-172, 343), + mapOf(x to 6u) to Rational(4, 147), + mapOf(y to 1u) to Rational(-183, 1), + mapOf(x to 1u, y to 1u) to Rational(-30988, 441), + mapOf(x to 2u, y to 1u) to Rational(-56137, 294), + mapOf(x to 3u, y to 1u) to Rational(204308, 1029), + mapOf(x to 4u, y to 1u) to Rational(-3263, 441), + mapOf(x to 5u, y to 1u) to Rational(2662, 441), + mapOf(x to 6u, y to 1u) to Rational(-52, 63), + mapOf(y to 2u) to Rational(-87119, 294), + mapOf(x to 1u, y to 2u) to Rational(1077919, 686), + mapOf(x to 2u, y to 2u) to Rational(-35209, 147), + mapOf(x to 3u, y to 2u) to Rational(15041, 147), + mapOf(x to 4u, y to 2u) to Rational(240889, 1323), + mapOf(x to 5u, y to 2u) to Rational(27778, 1323), + mapOf(x to 6u, y to 2u) to Rational(1327, 189), + mapOf(y to 3u) to Rational(1620, 7), + mapOf(x to 1u, y to 3u) to Rational(-25716, 49), + mapOf(x to 2u, y to 3u) to Rational(-32078, 49), + mapOf(x to 3u, y to 3u) to Rational(-704038, 441), + mapOf(x to 4u, y to 3u) to Rational(-30190, 63), + mapOf(x to 5u, y to 3u) to Rational(-5414, 63), + mapOf(x to 6u, y to 3u) to Rational(-104, 9), + mapOf(y to 4u) to Rational(225, 1), + mapOf(x to 1u, y to 4u) to Rational(-10560, 7), + mapOf(x to 2u, y to 4u) to Rational(44176, 21), + mapOf(x to 3u, y to 4u) to Rational(28996, 21), + mapOf(x to 4u, y to 4u) to Rational(2405, 7), + mapOf(x to 5u, y to 4u) to Rational(1240, 21), + mapOf(x to 6u, y to 4u) to Rational(16, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + y to LabeledPolynomialAsIs( + mapOf() to Rational(8, 2), + mapOf(x to 1u) to Rational(-15, 5), + mapOf(x to 2u) to Rational(2, 7), + mapOf(y to 1u) to Rational(-18, 7), + mapOf(x to 1u, y to 1u) to Rational(-16, 6), + mapOf(x to 2u, y to 1u) to Rational(-13, 3), + mapOf(y to 2u) to Rational(-5, 1), + mapOf(x to 1u, y to 2u) to Rational(17, 1), + mapOf(x to 2u, y to 2u) to Rational(8, 2), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-6, 1), + mapOf(x to 1u) to Rational(-9, 8), + mapOf(x to 2u) to Rational(17, 5), + mapOf(y to 1u) to Rational(-2, 3), + mapOf(x to 1u, y to 1u) to Rational(1, 5), + mapOf(x to 2u, y to 1u) to Rational(-11, 7), + mapOf(y to 2u) to Rational(13, 6), + mapOf(x to 1u, y to 2u) to Rational(-15, 2), + mapOf(x to 2u, y to 2u) to Rational(-14, 4), + ) + )), + "test 4'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-409, 6), + mapOf(x to 1u) to Rational(-376, 9), + mapOf(x to 2u) to Rational(-1781, 81), + mapOf(x to 3u) to Rational(-128, 27), + mapOf(x to 4u) to Rational(-8, 9), + mapOf(y to 1u) to Rational(18701, 210), + mapOf(x to 1u, y to 1u) to Rational(614183, 7560), + mapOf(x to 2u, y to 1u) to Rational(90941, 1890), + mapOf(x to 3u, y to 1u) to Rational(1802, 135), + mapOf(x to 4u, y to 1u) to Rational(112, 45), + mapOf(y to 2u) to Rational(181421, 315), + mapOf(x to 1u, y to 2u) to Rational(77813, 378), + mapOf(x to 2u, y to 2u) to Rational(598583, 7560), + mapOf(x to 3u, y to 2u) to Rational(85, 27), + mapOf(x to 4u, y to 2u) to Rational(2, 5), + mapOf(y to 3u) to Rational(130997, 315), + mapOf(x to 1u, y to 3u) to Rational(1093, 420), + mapOf(x to 2u, y to 3u) to Rational(9551, 2520), + mapOf(x to 3u, y to 3u) to Rational(-14, 45), + mapOf(x to 4u, y to 3u) to Rational(22, 45), + mapOf(y to 4u) to Rational(-2801, 9), + mapOf(x to 1u, y to 4u) to Rational(4033, 90), + mapOf(x to 2u, y to 4u) to Rational(6429, 80), + mapOf(x to 3u, y to 4u) to Rational(2851, 90), + mapOf(x to 4u, y to 4u) to Rational(293, 45), + mapOf(y to 5u) to Rational(-220, 1), + mapOf(x to 1u, y to 5u) to Rational(127, 1), + mapOf(x to 2u, y to 5u) to Rational(202, 5), + mapOf(x to 3u, y to 5u) to Rational(-63, 5), + mapOf(x to 4u, y to 5u) to Rational(-12, 5), + mapOf(y to 6u) to Rational(100, 1), + mapOf(x to 1u, y to 6u) to Rational(-80, 1), + mapOf(x to 2u, y to 6u) to Rational(-24, 1), + mapOf(x to 3u, y to 6u) to Rational(16, 1), + mapOf(x to 4u, y to 6u) to Rational(4, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5407, 9), + mapOf(x to 1u) to Rational(9568, 27), + mapOf(x to 2u) to Rational(4996, 27), + mapOf(x to 3u) to Rational(352, 9), + mapOf(x to 4u) to Rational(22, 3), + mapOf(y to 1u) to Rational(104411, 126), + mapOf(x to 1u, y to 1u) to Rational(6001, 126), + mapOf(x to 2u, y to 1u) to Rational(-796, 21), + mapOf(x to 3u, y to 1u) to Rational(-5389, 126), + mapOf(x to 4u, y to 1u) to Rational(-166, 21), + mapOf(y to 2u) to Rational(-35327, 126), + mapOf(x to 1u, y to 2u) to Rational(53, 252), + mapOf(x to 2u, y to 2u) to Rational(849197, 6048), + mapOf(x to 3u, y to 2u) to Rational(22361, 252), + mapOf(x to 4u, y to 2u) to Rational(773, 42), + mapOf(y to 3u) to Rational(-6067, 21), + mapOf(x to 1u, y to 3u) to Rational(39049, 126), + mapOf(x to 2u, y to 3u) to Rational(80303, 1008), + mapOf(x to 3u, y to 3u) to Rational(-3035, 63), + mapOf(x to 4u, y to 3u) to Rational(-209, 21), + mapOf(y to 4u) to Rational(3113, 21), + mapOf(x to 1u, y to 4u) to Rational(-22345, 126), + mapOf(x to 2u, y to 4u) to Rational(-30931, 1008), + mapOf(x to 3u, y to 4u) to Rational(5837, 126), + mapOf(x to 4u, y to 4u) to Rational(229, 21), + mapOf(y to 5u) to Rational(-2120, 21), + mapOf(x to 1u, y to 5u) to Rational(451, 7), + mapOf(x to 2u, y to 5u) to Rational(422, 21), + mapOf(x to 3u, y to 5u) to Rational(-181, 21), + mapOf(x to 4u, y to 5u) to Rational(-40, 21), + mapOf(y to 6u) to Rational(100, 3), + mapOf(x to 1u, y to 6u) to Rational(-80, 3), + mapOf(x to 2u, y to 6u) to Rational(-8, 1), + mapOf(x to 3u, y to 6u) to Rational(16, 3), + mapOf(x to 4u, y to 6u) to Rational(4, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(18, 1), + mapOf(x to 1u) to Rational(16, 3), + mapOf(x to 2u) to Rational(12, 6), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 4), + mapOf(x to 2u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(-10, 1), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + )), + "test 5" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-409, 6), + mapOf(x to 1u) to Rational(-376, 9), + mapOf(x to 2u) to Rational(-1781, 81), + mapOf(x to 3u) to Rational(-128, 27), + mapOf(x to 4u) to Rational(-8, 9), + mapOf(y to 1u) to Rational(18701, 210), + mapOf(x to 1u, y to 1u) to Rational(614183, 7560), + mapOf(x to 2u, y to 1u) to Rational(90941, 1890), + mapOf(x to 3u, y to 1u) to Rational(1802, 135), + mapOf(x to 4u, y to 1u) to Rational(112, 45), + mapOf(y to 2u) to Rational(181421, 315), + mapOf(x to 1u, y to 2u) to Rational(77813, 378), + mapOf(x to 2u, y to 2u) to Rational(598583, 7560), + mapOf(x to 3u, y to 2u) to Rational(85, 27), + mapOf(x to 4u, y to 2u) to Rational(2, 5), + mapOf(y to 3u) to Rational(130997, 315), + mapOf(x to 1u, y to 3u) to Rational(1093, 420), + mapOf(x to 2u, y to 3u) to Rational(9551, 2520), + mapOf(x to 3u, y to 3u) to Rational(-14, 45), + mapOf(x to 4u, y to 3u) to Rational(22, 45), + mapOf(y to 4u) to Rational(-2801, 9), + mapOf(x to 1u, y to 4u) to Rational(4033, 90), + mapOf(x to 2u, y to 4u) to Rational(6429, 80), + mapOf(x to 3u, y to 4u) to Rational(2851, 90), + mapOf(x to 4u, y to 4u) to Rational(293, 45), + mapOf(y to 5u) to Rational(-220, 1), + mapOf(x to 1u, y to 5u) to Rational(127, 1), + mapOf(x to 2u, y to 5u) to Rational(202, 5), + mapOf(x to 3u, y to 5u) to Rational(-63, 5), + mapOf(x to 4u, y to 5u) to Rational(-12, 5), + mapOf(y to 6u) to Rational(100, 1), + mapOf(x to 1u, y to 6u) to Rational(-80, 1), + mapOf(x to 2u, y to 6u) to Rational(-24, 1), + mapOf(x to 3u, y to 6u) to Rational(16, 1), + mapOf(x to 4u, y to 6u) to Rational(4, 1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5407, 9), + mapOf(x to 1u) to Rational(9568, 27), + mapOf(x to 2u) to Rational(4996, 27), + mapOf(x to 3u) to Rational(352, 9), + mapOf(x to 4u) to Rational(22, 3), + mapOf(y to 1u) to Rational(104411, 126), + mapOf(x to 1u, y to 1u) to Rational(6001, 126), + mapOf(x to 2u, y to 1u) to Rational(-796, 21), + mapOf(x to 3u, y to 1u) to Rational(-5389, 126), + mapOf(x to 4u, y to 1u) to Rational(-166, 21), + mapOf(y to 2u) to Rational(-35327, 126), + mapOf(x to 1u, y to 2u) to Rational(53, 252), + mapOf(x to 2u, y to 2u) to Rational(849197, 6048), + mapOf(x to 3u, y to 2u) to Rational(22361, 252), + mapOf(x to 4u, y to 2u) to Rational(773, 42), + mapOf(y to 3u) to Rational(-6067, 21), + mapOf(x to 1u, y to 3u) to Rational(39049, 126), + mapOf(x to 2u, y to 3u) to Rational(80303, 1008), + mapOf(x to 3u, y to 3u) to Rational(-3035, 63), + mapOf(x to 4u, y to 3u) to Rational(-209, 21), + mapOf(y to 4u) to Rational(3113, 21), + mapOf(x to 1u, y to 4u) to Rational(-22345, 126), + mapOf(x to 2u, y to 4u) to Rational(-30931, 1008), + mapOf(x to 3u, y to 4u) to Rational(5837, 126), + mapOf(x to 4u, y to 4u) to Rational(229, 21), + mapOf(y to 5u) to Rational(-2120, 21), + mapOf(x to 1u, y to 5u) to Rational(451, 7), + mapOf(x to 2u, y to 5u) to Rational(422, 21), + mapOf(x to 3u, y to 5u) to Rational(-181, 21), + mapOf(x to 4u, y to 5u) to Rational(-40, 21), + mapOf(y to 6u) to Rational(100, 3), + mapOf(x to 1u, y to 6u) to Rational(-80, 3), + mapOf(x to 2u, y to 6u) to Rational(-8, 1), + mapOf(x to 3u, y to 6u) to Rational(16, 3), + mapOf(x to 4u, y to 6u) to Rational(4, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + x to LabeledPolynomialAsIs( + mapOf() to Rational(18, 1), + mapOf(x to 1u) to Rational(16, 3), + mapOf(x to 2u) to Rational(12, 6), + mapOf(y to 1u) to Rational(13, 1), + mapOf(x to 1u, y to 1u) to Rational(-11, 4), + mapOf(x to 2u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(-10, 1), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-6, 1), + mapOf(x to 1u) to Rational(-9, 8), + mapOf(x to 2u) to Rational(17, 5), + mapOf(y to 1u) to Rational(-2, 3), + mapOf(x to 1u, y to 1u) to Rational(1, 5), + mapOf(x to 2u, y to 1u) to Rational(-11, 7), + mapOf(y to 2u) to Rational(13, 6), + mapOf(x to 1u, y to 2u) to Rational(-15, 2), + mapOf(x to 2u, y to 2u) to Rational(-14, 4), + ) + )), + "test 5'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 6), + mapOf(x to 1u) to Rational(1, 6), + mapOf(x to 2u) to Rational(-2, 9), + mapOf(y to 1u) to Rational(15, 1), + mapOf(x to 1u, y to 1u) to Rational(18, 7), + mapOf(x to 2u, y to 1u) to Rational(2, 5), + mapOf(y to 2u) to Rational(12, 9), + mapOf(x to 1u, y to 2u) to Rational(-3, 5), + mapOf(x to 2u, y to 2u) to Rational(4, 4), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-11, 9), + mapOf(x to 1u) to Rational(4, 9), + mapOf(x to 2u) to Rational(11, 6), + mapOf(y to 1u) to Rational(-5, 6), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(-1, 7), + mapOf(y to 2u) to Rational(9, 1), + mapOf(x to 1u, y to 2u) to Rational(6, 7), + mapOf(x to 2u, y to 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + iota to LabeledPolynomialAsIs( + mapOf() to Rational(-6, 1), + mapOf(x to 1u) to Rational(-9, 8), + mapOf(x to 2u) to Rational(17, 5), + mapOf(y to 1u) to Rational(-2, 3), + mapOf(x to 1u, y to 1u) to Rational(1, 5), + mapOf(x to 2u, y to 1u) to Rational(-11, 7), + mapOf(y to 2u) to Rational(13, 6), + mapOf(x to 1u, y to 2u) to Rational(-15, 2), + mapOf(x to 2u, y to 2u) to Rational(-14, 4), + ) + )), + "test 6'" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction_Map() { + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(0) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ), + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(-17166109, 793800), + mapOf(x to 3u, y to 1u) to Rational(-930960143, 5556600), + mapOf(x to 2u, y to 2u) to Rational(-144665109691, 350065800), + mapOf(x to 1u, y to 3u) to Rational(-17232577, 52920), + mapOf(y to 4u) to Rational(-68141, 1323), + ), + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(-57522533, 14288400), + mapOf(x to 3u, y to 1u) to Rational(-13085162953, 300056400), + mapOf(x to 2u, y to 2u) to Rational(-92093367341, 525098700), + mapOf(x to 1u, y to 3u) to Rational(-1979342797, 6667920), + mapOf(y to 4u) to Rational(-3082727, 21168), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(11, 5), + mapOf(y to 1u) to Rational(8, 4), + ), + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1, 9), + mapOf(y to 1u) to Rational(11, 7), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-2, 7), + mapOf(y to 1u) to Rational(-4, 3), + ), + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(3, 6), + mapOf(y to 1u) to Rational(12, 8), + ) + ), + )), + "test 2" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-130778291, 76800), + mapOf(x to 1u) to Rational(-445270919, 230400), + mapOf(x to 2u) to Rational(44578444937, 14515200), + mapOf(x to 3u) to Rational(17329402153, 1555200), + mapOf(x to 4u) to Rational(89239926809, 2332800), + mapOf(x to 5u) to Rational(2808812267, 145152), + mapOf(x to 6u) to Rational(-21362661007, 725760), + mapOf(x to 7u) to Rational(-258455443, 2016), + mapOf(x to 8u) to Rational(-21454693, 96), + mapOf(y to 1u) to Rational(-1002137, 15360), + mapOf(x to 1u, y to 1u) to Rational(-1704849697, 430080), + mapOf(x to 2u, y to 1u) to Rational(-57657676789, 4838400), + mapOf(x to 3u, y to 1u) to Rational(-101331731, 89600), + mapOf(x to 4u, y to 1u) to Rational(5362280079329, 130636800), + mapOf(x to 5u, y to 1u) to Rational(4069896167053, 130636800), + mapOf(x to 6u, y to 1u) to Rational(12011514569, 544320), + mapOf(x to 7u, y to 1u) to Rational(138293195623, 725760), + mapOf(x to 8u, y to 1u) to Rational(6228779419, 48384), + mapOf(y to 2u) to Rational(-32395872823, 8064000), + mapOf(x to 1u, y to 2u) to Rational(-7398505523, 2304000), + mapOf(x to 2u, y to 2u) to Rational(95217051699521, 3048192000), + mapOf(x to 3u, y to 2u) to Rational(198026968812079, 3657830400), + mapOf(x to 4u, y to 2u) to Rational(4291645618499, 228614400), + mapOf(x to 5u, y to 2u) to Rational(-33211690942439, 914457600), + mapOf(x to 6u, y to 2u) to Rational(-637385538163153, 1371686400), + mapOf(x to 7u, y to 2u) to Rational(-138671528276273, 182891520), + mapOf(x to 8u, y to 2u) to Rational(-14566368751, 217728), + mapOf(y to 3u) to Rational(-10538718719, 2016000), + mapOf(x to 1u, y to 3u) to Rational(-1844485375199, 84672000), + mapOf(x to 2u, y to 3u) to Rational(103968665891, 12096000), + mapOf(x to 3u, y to 3u) to Rational(175402107278351, 1828915200), + mapOf(x to 4u, y to 3u) to Rational(8020699588879, 114307200), + mapOf(x to 5u, y to 3u) to Rational(3414841894991, 38102400), + mapOf(x to 6u, y to 3u) to Rational(1848405591611, 4665600), + mapOf(x to 7u, y to 3u) to Rational(39486708738989, 137168640), + mapOf(x to 8u, y to 3u) to Rational(255926289517, 9144576), + mapOf(y to 4u) to Rational(-655379564629, 105840000), + mapOf(x to 1u, y to 4u) to Rational(-208336039441, 127008000), + mapOf(x to 2u, y to 4u) to Rational(40173146771411, 1143072000), + mapOf(x to 3u, y to 4u) to Rational(150473493581239, 2667168000), + mapOf(x to 4u, y to 4u) to Rational(38833783990483, 1143072000), + mapOf(x to 5u, y to 4u) to Rational(-1963676248203053, 4800902400), + mapOf(x to 6u, y to 4u) to Rational(-2598759412825747, 3200601600), + mapOf(x to 7u, y to 4u) to Rational(-192895352019667, 1280240640), + mapOf(x to 8u, y to 4u) to Rational(3737382679, 6858432), + mapOf(y to 5u) to Rational(-16959378721, 1890000), + mapOf(x to 1u, y to 5u) to Rational(-1864802244743, 79380000), + mapOf(x to 2u, y to 5u) to Rational(13449261536489, 666792000), + mapOf(x to 3u, y to 5u) to Rational(215272234137329, 2667168000), + mapOf(x to 4u, y to 5u) to Rational(6040691379277, 83349000), + mapOf(x to 5u, y to 5u) to Rational(153687143525887, 800150400), + mapOf(x to 6u, y to 5u) to Rational(475602854903563, 2400451200), + mapOf(x to 7u, y to 5u) to Rational(27315599358749, 640120320), + mapOf(x to 8u, y to 5u) to Rational(-2630413357, 10668672), + mapOf(y to 6u) to Rational(-6654999511, 2646000), + mapOf(x to 1u, y to 6u) to Rational(-67885252327, 15876000), + mapOf(x to 2u, y to 6u) to Rational(5786776220983, 2667168000), + mapOf(x to 3u, y to 6u) to Rational(60615922629083, 1143072000), + mapOf(x to 4u, y to 6u) to Rational(-34703539637627407, 672126336000), + mapOf(x to 5u, y to 6u) to Rational(-744694192134101, 2240421120), + mapOf(x to 6u, y to 6u) to Rational(-1782470617231, 14817600), + mapOf(x to 7u, y to 6u) to Rational(59123208433, 8890560), + mapOf(x to 8u, y to 6u) to Rational(-141653, 5292), + mapOf(y to 7u) to Rational(-338051969, 441000), + mapOf(x to 1u, y to 7u) to Rational(468850013, 1764000), + mapOf(x to 2u, y to 7u) to Rational(2102343426101, 222264000), + mapOf(x to 3u, y to 7u) to Rational(7836130602007, 1333584000), + mapOf(x to 4u, y to 7u) to Rational(16239111865997, 746807040), + mapOf(x to 5u, y to 7u) to Rational(3824649185383, 88905600), + mapOf(x to 6u, y to 7u) to Rational(56058614459, 3457440), + mapOf(x to 7u, y to 7u) to Rational(-396766339, 493920), + mapOf(x to 8u, y to 7u) to Rational(-165147, 2744), + mapOf(y to 8u) to Rational(-3088619, 58800), + mapOf(x to 1u, y to 8u) to Rational(155343347, 88200), + mapOf(x to 2u, y to 8u) to Rational(100098736469, 7408800), + mapOf(x to 3u, y to 8u) to Rational(109725511381, 7408800), + mapOf(x to 4u, y to 8u) to Rational(-2431199641013, 59270400), + mapOf(x to 5u, y to 8u) to Rational(-102872383249, 3457440), + mapOf(x to 6u, y to 8u) to Rational(1449461309, 576240), + mapOf(x to 7u, y to 8u) to Rational(812775, 1372), + mapOf(x to 8u, y to 8u) to Rational(-16461, 343) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(164202773, 230400), + mapOf(x to 1u) to Rational(-70345303, 518400), + mapOf(x to 2u) to Rational(-4229702731, 4665600), + mapOf(x to 3u) to Rational(3262171027, 6998400), + mapOf(x to 4u) to Rational(-25423104169, 13996800), + mapOf(x to 5u) to Rational(64061869, 349920), + mapOf(x to 6u) to Rational(-1655878091, 116640), + mapOf(x to 7u) to Rational(-7991441, 648), + mapOf(x to 8u) to Rational(-502591, 18), + mapOf(y to 1u) to Rational(-8780429, 3840), + mapOf(x to 1u, y to 1u) to Rational(434272361, 115200), + mapOf(x to 2u, y to 1u) to Rational(429825727, 41472), + mapOf(x to 3u, y to 1u) to Rational(-10066790339, 6998400), + mapOf(x to 4u, y to 1u) to Rational(70022035471, 20995200), + mapOf(x to 5u, y to 1u) to Rational(-32070283493, 1399680), + mapOf(x to 6u, y to 1u) to Rational(-22051101001, 1399680), + mapOf(x to 7u, y to 1u) to Rational(-126493427, 12960), + mapOf(x to 8u, y to 1u) to Rational(3050245, 864), + mapOf(y to 2u) to Rational(-1194654631, 345600), + mapOf(x to 1u, y to 2u) to Rational(-542961452671, 31104000), + mapOf(x to 2u, y to 2u) to Rational(-234000873607, 48988800), + mapOf(x to 3u, y to 2u) to Rational(140520538087, 3628800), + mapOf(x to 4u, y to 2u) to Rational(9215088876563, 130636800), + mapOf(x to 5u, y to 2u) to Rational(27590569647253, 293932800), + mapOf(x to 6u, y to 2u) to Rational(5129057792891, 97977600), + mapOf(x to 7u, y to 2u) to Rational(-106334191, 5103), + mapOf(x to 8u, y to 2u) to Rational(-1024113911, 435456), + mapOf(y to 3u) to Rational(76223843, 6000), + mapOf(x to 1u, y to 3u) to Rational(57425857357, 2592000), + mapOf(x to 2u, y to 3u) to Rational(-2044736497573, 46656000), + mapOf(x to 3u, y to 3u) to Rational(-26155810120031, 293932800), + mapOf(x to 4u, y to 3u) to Rational(-1064419459813, 6998400), + mapOf(x to 5u, y to 3u) to Rational(-753782018389, 4082400), + mapOf(x to 6u, y to 3u) to Rational(-291973360873, 2799360), + mapOf(x to 7u, y to 3u) to Rational(-46372122599, 816480), + mapOf(x to 8u, y to 3u) to Rational(3579859657, 653184), + mapOf(y to 4u) to Rational(-13374241901, 4320000), + mapOf(x to 1u, y to 4u) to Rational(306606499811, 54432000), + mapOf(x to 2u, y to 4u) to Rational(964267124745437, 13716864000), + mapOf(x to 3u, y to 4u) to Rational(21603809415373, 182891520), + mapOf(x to 4u, y to 4u) to Rational(1097860214654027, 6858432000), + mapOf(x to 5u, y to 4u) to Rational(161615254570669, 914457600), + mapOf(x to 6u, y to 4u) to Rational(758415239461, 22861440), + mapOf(x to 7u, y to 4u) to Rational(2585568355471, 274337280), + mapOf(x to 8u, y to 4u) to Rational(-70433747863, 9144576), + mapOf(y to 5u) to Rational(-9582586217, 2520000), + mapOf(x to 1u, y to 5u) to Rational(-19093471394171, 635040000), + mapOf(x to 2u, y to 5u) to Rational(-13010261944411, 381024000), + mapOf(x to 3u, y to 5u) to Rational(-259039825301861, 4572288000), + mapOf(x to 4u, y to 5u) to Rational(-305081119071079, 2286144000), + mapOf(x to 5u, y to 5u) to Rational(-1923114383311, 19595520), + mapOf(x to 6u, y to 5u) to Rational(-14181787253231, 228614400), + mapOf(x to 7u, y to 5u) to Rational(-3959584789, 4354560), + mapOf(x to 8u, y to 5u) to Rational(4691742523, 762048), + mapOf(y to 6u) to Rational(-588323437, 180000), + mapOf(x to 1u, y to 6u) to Rational(5952234691, 52920000), + mapOf(x to 2u, y to 6u) to Rational(21001851056959, 1088640000), + mapOf(x to 3u, y to 6u) to Rational(84668034357563, 2133734400), + mapOf(x to 4u, y to 6u) to Rational(2029754605811557, 25604812800), + mapOf(x to 5u, y to 6u) to Rational(11721216739823, 426746880), + mapOf(x to 6u, y to 6u) to Rational(-8275903187003, 2133734400), + mapOf(x to 7u, y to 6u) to Rational(-4730447299, 2540160), + mapOf(x to 8u, y to 6u) to Rational(-46069985, 21168), + mapOf(y to 7u) to Rational(-75711301, 117600), + mapOf(x to 1u, y to 7u) to Rational(32430417413, 7056000), + mapOf(x to 2u, y to 7u) to Rational(677988533153, 98784000), + mapOf(x to 3u, y to 7u) to Rational(-948417645827, 71124480), + mapOf(x to 4u, y to 7u) to Rational(-11320265215207, 711244800), + mapOf(x to 5u, y to 7u) to Rational(-676438627783, 50803200), + mapOf(x to 6u, y to 7u) to Rational(-7382274253, 1975680), + mapOf(x to 7u, y to 7u) to Rational(6505733, 2205), + mapOf(x to 8u, y to 7u) to Rational(450137, 882), + mapOf(y to 8u) to Rational(-8368253, 78400), + mapOf(x to 1u, y to 8u) to Rational(6833783, 117600), + mapOf(x to 2u, y to 8u) to Rational(4528971133, 5927040), + mapOf(x to 3u, y to 8u) to Rational(146252636617, 29635200), + mapOf(x to 4u, y to 8u) to Rational(8321882556889, 1659571200), + mapOf(x to 5u, y to 8u) to Rational(-4686033011, 1975680), + mapOf(x to 6u, y to 8u) to Rational(-1074445963, 987840), + mapOf(x to 7u, y to 8u) to Rational(-142313, 588), + mapOf(x to 8u, y to 8u) to Rational(-4281, 49) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-17, 5), + mapOf(x to 1u) to Rational(2, 6), + mapOf(x to 2u) to Rational(14, 1), + mapOf(y to 1u) to Rational(-6, 6), + mapOf(x to 1u, y to 1u) to Rational(-7, 3), + mapOf(x to 2u, y to 1u) to Rational(-2, 9), + mapOf(y to 2u) to Rational(-9, 6), + mapOf(x to 1u, y to 2u) to Rational(17, 4), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5, 4), + mapOf(x to 1u) to Rational(-5, 9), + mapOf(x to 2u) to Rational(-3, 6), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(14, 5), + mapOf(x to 2u, y to 1u) to Rational(5, 2), + mapOf(y to 2u) to Rational(-18, 7), + mapOf(x to 1u, y to 2u) to Rational(-8, 2), + mapOf(x to 2u, y to 2u) to Rational(18, 9), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(14, 4), + mapOf(x to 1u) to Rational(7, 6), + mapOf(x to 2u) to Rational(7, 2), + mapOf(y to 1u) to Rational(-15, 2), + mapOf(x to 1u, y to 1u) to Rational(-13, 8), + mapOf(x to 2u, y to 1u) to Rational(-14, 3), + mapOf(y to 2u) to Rational(-7, 6), + mapOf(x to 1u, y to 2u) to Rational(7, 4), + mapOf(x to 2u, y to 2u) to Rational(9, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-7, 4), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(-16, 2), + mapOf(y to 1u) to Rational(-15, 5), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(5, 4), + mapOf(y to 2u) to Rational(-12, 5), + mapOf(x to 1u, y to 2u) to Rational(-18, 2), + mapOf(x to 2u, y to 2u) to Rational(6, 7), + ) + ), + )), + "test 3" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-130778291, 76800), + mapOf(x to 1u) to Rational(-445270919, 230400), + mapOf(x to 2u) to Rational(44578444937, 14515200), + mapOf(x to 3u) to Rational(17329402153, 1555200), + mapOf(x to 4u) to Rational(89239926809, 2332800), + mapOf(x to 5u) to Rational(2808812267, 145152), + mapOf(x to 6u) to Rational(-21362661007, 725760), + mapOf(x to 7u) to Rational(-258455443, 2016), + mapOf(x to 8u) to Rational(-21454693, 96), + mapOf(y to 1u) to Rational(-1002137, 15360), + mapOf(x to 1u, y to 1u) to Rational(-1704849697, 430080), + mapOf(x to 2u, y to 1u) to Rational(-57657676789, 4838400), + mapOf(x to 3u, y to 1u) to Rational(-101331731, 89600), + mapOf(x to 4u, y to 1u) to Rational(5362280079329, 130636800), + mapOf(x to 5u, y to 1u) to Rational(4069896167053, 130636800), + mapOf(x to 6u, y to 1u) to Rational(12011514569, 544320), + mapOf(x to 7u, y to 1u) to Rational(138293195623, 725760), + mapOf(x to 8u, y to 1u) to Rational(6228779419, 48384), + mapOf(y to 2u) to Rational(-32395872823, 8064000), + mapOf(x to 1u, y to 2u) to Rational(-7398505523, 2304000), + mapOf(x to 2u, y to 2u) to Rational(95217051699521, 3048192000), + mapOf(x to 3u, y to 2u) to Rational(198026968812079, 3657830400), + mapOf(x to 4u, y to 2u) to Rational(4291645618499, 228614400), + mapOf(x to 5u, y to 2u) to Rational(-33211690942439, 914457600), + mapOf(x to 6u, y to 2u) to Rational(-637385538163153, 1371686400), + mapOf(x to 7u, y to 2u) to Rational(-138671528276273, 182891520), + mapOf(x to 8u, y to 2u) to Rational(-14566368751, 217728), + mapOf(y to 3u) to Rational(-10538718719, 2016000), + mapOf(x to 1u, y to 3u) to Rational(-1844485375199, 84672000), + mapOf(x to 2u, y to 3u) to Rational(103968665891, 12096000), + mapOf(x to 3u, y to 3u) to Rational(175402107278351, 1828915200), + mapOf(x to 4u, y to 3u) to Rational(8020699588879, 114307200), + mapOf(x to 5u, y to 3u) to Rational(3414841894991, 38102400), + mapOf(x to 6u, y to 3u) to Rational(1848405591611, 4665600), + mapOf(x to 7u, y to 3u) to Rational(39486708738989, 137168640), + mapOf(x to 8u, y to 3u) to Rational(255926289517, 9144576), + mapOf(y to 4u) to Rational(-655379564629, 105840000), + mapOf(x to 1u, y to 4u) to Rational(-208336039441, 127008000), + mapOf(x to 2u, y to 4u) to Rational(40173146771411, 1143072000), + mapOf(x to 3u, y to 4u) to Rational(150473493581239, 2667168000), + mapOf(x to 4u, y to 4u) to Rational(38833783990483, 1143072000), + mapOf(x to 5u, y to 4u) to Rational(-1963676248203053, 4800902400), + mapOf(x to 6u, y to 4u) to Rational(-2598759412825747, 3200601600), + mapOf(x to 7u, y to 4u) to Rational(-192895352019667, 1280240640), + mapOf(x to 8u, y to 4u) to Rational(3737382679, 6858432), + mapOf(y to 5u) to Rational(-16959378721, 1890000), + mapOf(x to 1u, y to 5u) to Rational(-1864802244743, 79380000), + mapOf(x to 2u, y to 5u) to Rational(13449261536489, 666792000), + mapOf(x to 3u, y to 5u) to Rational(215272234137329, 2667168000), + mapOf(x to 4u, y to 5u) to Rational(6040691379277, 83349000), + mapOf(x to 5u, y to 5u) to Rational(153687143525887, 800150400), + mapOf(x to 6u, y to 5u) to Rational(475602854903563, 2400451200), + mapOf(x to 7u, y to 5u) to Rational(27315599358749, 640120320), + mapOf(x to 8u, y to 5u) to Rational(-2630413357, 10668672), + mapOf(y to 6u) to Rational(-6654999511, 2646000), + mapOf(x to 1u, y to 6u) to Rational(-67885252327, 15876000), + mapOf(x to 2u, y to 6u) to Rational(5786776220983, 2667168000), + mapOf(x to 3u, y to 6u) to Rational(60615922629083, 1143072000), + mapOf(x to 4u, y to 6u) to Rational(-34703539637627407, 672126336000), + mapOf(x to 5u, y to 6u) to Rational(-744694192134101, 2240421120), + mapOf(x to 6u, y to 6u) to Rational(-1782470617231, 14817600), + mapOf(x to 7u, y to 6u) to Rational(59123208433, 8890560), + mapOf(x to 8u, y to 6u) to Rational(-141653, 5292), + mapOf(y to 7u) to Rational(-338051969, 441000), + mapOf(x to 1u, y to 7u) to Rational(468850013, 1764000), + mapOf(x to 2u, y to 7u) to Rational(2102343426101, 222264000), + mapOf(x to 3u, y to 7u) to Rational(7836130602007, 1333584000), + mapOf(x to 4u, y to 7u) to Rational(16239111865997, 746807040), + mapOf(x to 5u, y to 7u) to Rational(3824649185383, 88905600), + mapOf(x to 6u, y to 7u) to Rational(56058614459, 3457440), + mapOf(x to 7u, y to 7u) to Rational(-396766339, 493920), + mapOf(x to 8u, y to 7u) to Rational(-165147, 2744), + mapOf(y to 8u) to Rational(-3088619, 58800), + mapOf(x to 1u, y to 8u) to Rational(155343347, 88200), + mapOf(x to 2u, y to 8u) to Rational(100098736469, 7408800), + mapOf(x to 3u, y to 8u) to Rational(109725511381, 7408800), + mapOf(x to 4u, y to 8u) to Rational(-2431199641013, 59270400), + mapOf(x to 5u, y to 8u) to Rational(-102872383249, 3457440), + mapOf(x to 6u, y to 8u) to Rational(1449461309, 576240), + mapOf(x to 7u, y to 8u) to Rational(812775, 1372), + mapOf(x to 8u, y to 8u) to Rational(-16461, 343) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(164202773, 230400), + mapOf(x to 1u) to Rational(-70345303, 518400), + mapOf(x to 2u) to Rational(-4229702731, 4665600), + mapOf(x to 3u) to Rational(3262171027, 6998400), + mapOf(x to 4u) to Rational(-25423104169, 13996800), + mapOf(x to 5u) to Rational(64061869, 349920), + mapOf(x to 6u) to Rational(-1655878091, 116640), + mapOf(x to 7u) to Rational(-7991441, 648), + mapOf(x to 8u) to Rational(-502591, 18), + mapOf(y to 1u) to Rational(-8780429, 3840), + mapOf(x to 1u, y to 1u) to Rational(434272361, 115200), + mapOf(x to 2u, y to 1u) to Rational(429825727, 41472), + mapOf(x to 3u, y to 1u) to Rational(-10066790339, 6998400), + mapOf(x to 4u, y to 1u) to Rational(70022035471, 20995200), + mapOf(x to 5u, y to 1u) to Rational(-32070283493, 1399680), + mapOf(x to 6u, y to 1u) to Rational(-22051101001, 1399680), + mapOf(x to 7u, y to 1u) to Rational(-126493427, 12960), + mapOf(x to 8u, y to 1u) to Rational(3050245, 864), + mapOf(y to 2u) to Rational(-1194654631, 345600), + mapOf(x to 1u, y to 2u) to Rational(-542961452671, 31104000), + mapOf(x to 2u, y to 2u) to Rational(-234000873607, 48988800), + mapOf(x to 3u, y to 2u) to Rational(140520538087, 3628800), + mapOf(x to 4u, y to 2u) to Rational(9215088876563, 130636800), + mapOf(x to 5u, y to 2u) to Rational(27590569647253, 293932800), + mapOf(x to 6u, y to 2u) to Rational(5129057792891, 97977600), + mapOf(x to 7u, y to 2u) to Rational(-106334191, 5103), + mapOf(x to 8u, y to 2u) to Rational(-1024113911, 435456), + mapOf(y to 3u) to Rational(76223843, 6000), + mapOf(x to 1u, y to 3u) to Rational(57425857357, 2592000), + mapOf(x to 2u, y to 3u) to Rational(-2044736497573, 46656000), + mapOf(x to 3u, y to 3u) to Rational(-26155810120031, 293932800), + mapOf(x to 4u, y to 3u) to Rational(-1064419459813, 6998400), + mapOf(x to 5u, y to 3u) to Rational(-753782018389, 4082400), + mapOf(x to 6u, y to 3u) to Rational(-291973360873, 2799360), + mapOf(x to 7u, y to 3u) to Rational(-46372122599, 816480), + mapOf(x to 8u, y to 3u) to Rational(3579859657, 653184), + mapOf(y to 4u) to Rational(-13374241901, 4320000), + mapOf(x to 1u, y to 4u) to Rational(306606499811, 54432000), + mapOf(x to 2u, y to 4u) to Rational(964267124745437, 13716864000), + mapOf(x to 3u, y to 4u) to Rational(21603809415373, 182891520), + mapOf(x to 4u, y to 4u) to Rational(1097860214654027, 6858432000), + mapOf(x to 5u, y to 4u) to Rational(161615254570669, 914457600), + mapOf(x to 6u, y to 4u) to Rational(758415239461, 22861440), + mapOf(x to 7u, y to 4u) to Rational(2585568355471, 274337280), + mapOf(x to 8u, y to 4u) to Rational(-70433747863, 9144576), + mapOf(y to 5u) to Rational(-9582586217, 2520000), + mapOf(x to 1u, y to 5u) to Rational(-19093471394171, 635040000), + mapOf(x to 2u, y to 5u) to Rational(-13010261944411, 381024000), + mapOf(x to 3u, y to 5u) to Rational(-259039825301861, 4572288000), + mapOf(x to 4u, y to 5u) to Rational(-305081119071079, 2286144000), + mapOf(x to 5u, y to 5u) to Rational(-1923114383311, 19595520), + mapOf(x to 6u, y to 5u) to Rational(-14181787253231, 228614400), + mapOf(x to 7u, y to 5u) to Rational(-3959584789, 4354560), + mapOf(x to 8u, y to 5u) to Rational(4691742523, 762048), + mapOf(y to 6u) to Rational(-588323437, 180000), + mapOf(x to 1u, y to 6u) to Rational(5952234691, 52920000), + mapOf(x to 2u, y to 6u) to Rational(21001851056959, 1088640000), + mapOf(x to 3u, y to 6u) to Rational(84668034357563, 2133734400), + mapOf(x to 4u, y to 6u) to Rational(2029754605811557, 25604812800), + mapOf(x to 5u, y to 6u) to Rational(11721216739823, 426746880), + mapOf(x to 6u, y to 6u) to Rational(-8275903187003, 2133734400), + mapOf(x to 7u, y to 6u) to Rational(-4730447299, 2540160), + mapOf(x to 8u, y to 6u) to Rational(-46069985, 21168), + mapOf(y to 7u) to Rational(-75711301, 117600), + mapOf(x to 1u, y to 7u) to Rational(32430417413, 7056000), + mapOf(x to 2u, y to 7u) to Rational(677988533153, 98784000), + mapOf(x to 3u, y to 7u) to Rational(-948417645827, 71124480), + mapOf(x to 4u, y to 7u) to Rational(-11320265215207, 711244800), + mapOf(x to 5u, y to 7u) to Rational(-676438627783, 50803200), + mapOf(x to 6u, y to 7u) to Rational(-7382274253, 1975680), + mapOf(x to 7u, y to 7u) to Rational(6505733, 2205), + mapOf(x to 8u, y to 7u) to Rational(450137, 882), + mapOf(y to 8u) to Rational(-8368253, 78400), + mapOf(x to 1u, y to 8u) to Rational(6833783, 117600), + mapOf(x to 2u, y to 8u) to Rational(4528971133, 5927040), + mapOf(x to 3u, y to 8u) to Rational(146252636617, 29635200), + mapOf(x to 4u, y to 8u) to Rational(8321882556889, 1659571200), + mapOf(x to 5u, y to 8u) to Rational(-4686033011, 1975680), + mapOf(x to 6u, y to 8u) to Rational(-1074445963, 987840), + mapOf(x to 7u, y to 8u) to Rational(-142313, 588), + mapOf(x to 8u, y to 8u) to Rational(-4281, 49) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-17, 5), + mapOf(x to 1u) to Rational(2, 6), + mapOf(x to 2u) to Rational(14, 1), + mapOf(y to 1u) to Rational(-6, 6), + mapOf(x to 1u, y to 1u) to Rational(-7, 3), + mapOf(x to 2u, y to 1u) to Rational(-2, 9), + mapOf(y to 2u) to Rational(-9, 6), + mapOf(x to 1u, y to 2u) to Rational(17, 4), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5, 4), + mapOf(x to 1u) to Rational(-5, 9), + mapOf(x to 2u) to Rational(-3, 6), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(14, 5), + mapOf(x to 2u, y to 1u) to Rational(5, 2), + mapOf(y to 2u) to Rational(-18, 7), + mapOf(x to 1u, y to 2u) to Rational(-8, 2), + mapOf(x to 2u, y to 2u) to Rational(18, 9), + ) + ), + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(14, 4), + mapOf(x to 1u) to Rational(7, 6), + mapOf(x to 2u) to Rational(7, 2), + mapOf(y to 1u) to Rational(-15, 2), + mapOf(x to 1u, y to 1u) to Rational(-13, 8), + mapOf(x to 2u, y to 1u) to Rational(-14, 3), + mapOf(y to 2u) to Rational(-7, 6), + mapOf(x to 1u, y to 2u) to Rational(7, 4), + mapOf(x to 2u, y to 2u) to Rational(9, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-7, 4), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(-16, 2), + mapOf(y to 1u) to Rational(-15, 5), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(5, 4), + mapOf(y to 2u) to Rational(-12, 5), + mapOf(x to 1u, y to 2u) to Rational(-18, 2), + mapOf(x to 2u, y to 2u) to Rational(6, 7), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 8), + mapOf(x to 1u) to Rational(-12, 6), + mapOf(x to 2u) to Rational(7, 6), + mapOf(y to 1u) to Rational(-10, 4), + mapOf(x to 1u, y to 1u) to Rational(-7, 6), + mapOf(x to 2u, y to 1u) to Rational(8, 9), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(5, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(10, 6), + mapOf(x to 1u) to Rational(-18, 6), + mapOf(x to 2u) to Rational(5, 1), + mapOf(y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(8, 4), + mapOf(x to 2u, y to 1u) to Rational(-4, 9), + mapOf(y to 2u) to Rational(-6, 5), + mapOf(x to 1u, y to 2u) to Rational(-15, 8), + mapOf(x to 2u, y to 2u) to Rational(-18, 5), + ) + ), + )), + "test 3'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(2303, 64), + mapOf(x to 1u) to Rational(31843, 192), + mapOf(x to 2u) to Rational(118891, 576), + mapOf(x to 3u) to Rational(94453, 168), + mapOf(x to 4u) to Rational(-179203, 1512), + mapOf(x to 5u) to Rational(-16979, 126), + mapOf(x to 6u) to Rational(-13499, 12), + mapOf(y to 1u) to Rational(-4767, 64), + mapOf(x to 1u, y to 1u) to Rational(-58689, 256), + mapOf(x to 2u, y to 1u) to Rational(-757333, 4032), + mapOf(x to 3u, y to 1u) to Rational(-4921205, 4032), + mapOf(x to 4u, y to 1u) to Rational(-2930815, 4032), + mapOf(x to 5u, y to 1u) to Rational(-398803, 1512), + mapOf(x to 6u, y to 1u) to Rational(18835, 36), + mapOf(y to 2u) to Rational(224101, 960), + mapOf(x to 1u, y to 2u) to Rational(9139699, 40320), + mapOf(x to 2u, y to 2u) to Rational(3848803, 5760), + mapOf(x to 3u, y to 2u) to Rational(93102371, 241920), + mapOf(x to 4u, y to 2u) to Rational(-65821229, 141120), + mapOf(x to 5u, y to 2u) to Rational(-15675899, 7056), + mapOf(x to 6u, y to 2u) to Rational(10459, 189), + mapOf(y to 3u) to Rational(2411, 16), + mapOf(x to 1u, y to 3u) to Rational(1294543, 10080), + mapOf(x to 2u, y to 3u) to Rational(-1740199, 1440), + mapOf(x to 3u, y to 3u) to Rational(-266994841, 282240), + mapOf(x to 4u, y to 3u) to Rational(-41261893, 211680), + mapOf(x to 5u, y to 3u) to Rational(1717357, 3528), + mapOf(x to 6u, y to 3u) to Rational(69, 14), + mapOf(y to 4u) to Rational(13231, 360), + mapOf(x to 1u, y to 4u) to Rational(4858831, 25200), + mapOf(x to 2u, y to 4u) to Rational(15565759, 75600), + mapOf(x to 3u, y to 4u) to Rational(-15583391, 35280), + mapOf(x to 4u, y to 4u) to Rational(-13345747, 11760), + mapOf(x to 5u, y to 4u) to Rational(140103, 686), + mapOf(x to 6u, y to 4u) to Rational(-765, 49) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(31409, 576), + mapOf(x to 1u) to Rational(-337099, 1728), + mapOf(x to 2u) to Rational(-211429, 1728), + mapOf(x to 3u) to Rational(-259241, 432), + mapOf(x to 4u) to Rational(-13777, 36), + mapOf(x to 5u) to Rational(-41389, 72), + mapOf(x to 6u) to Rational(-7679, 48), + mapOf(y to 1u) to Rational(-3269, 12), + mapOf(x to 1u, y to 1u) to Rational(629569, 864), + mapOf(x to 2u, y to 1u) to Rational(53867, 324), + mapOf(x to 3u, y to 1u) to Rational(2290577, 1728), + mapOf(x to 4u, y to 1u) to Rational(101507, 216), + mapOf(x to 5u, y to 1u) to Rational(213109, 288), + mapOf(x to 6u, y to 1u) to Rational(17927, 144), + mapOf(y to 2u) to Rational(314587, 1080), + mapOf(x to 1u, y to 2u) to Rational(-109771, 144), + mapOf(x to 2u, y to 2u) to Rational(-6469, 16), + mapOf(x to 3u, y to 2u) to Rational(-298291681, 181440), + mapOf(x to 4u, y to 2u) to Rational(-59147357, 48384), + mapOf(x to 5u, y to 2u) to Rational(-4982365, 6048), + mapOf(x to 6u, y to 2u) to Rational(-18727, 576), + mapOf(y to 3u) to Rational(12379, 90), + mapOf(x to 1u, y to 3u) to Rational(-542911, 1620), + mapOf(x to 2u, y to 3u) to Rational(143123, 1260), + mapOf(x to 3u, y to 3u) to Rational(9859177, 30240), + mapOf(x to 4u, y to 3u) to Rational(9312529, 20160), + mapOf(x to 5u, y to 3u) to Rational(207001, 672), + mapOf(x to 6u, y to 3u) to Rational(203, 24), + mapOf(y to 4u) to Rational(9442, 675), + mapOf(x to 1u, y to 4u) to Rational(-13729, 300), + mapOf(x to 2u, y to 4u) to Rational(-3490471, 25200), + mapOf(x to 3u, y to 4u) to Rational(-333031, 840), + mapOf(x to 4u, y to 4u) to Rational(-7572211, 47040), + mapOf(x to 5u, y to 4u) to Rational(-1189, 56), + mapOf(x to 6u, y to 4u) to Rational(-405, 196) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(14, 4), + mapOf(x to 1u) to Rational(7, 6), + mapOf(x to 2u) to Rational(7, 2), + mapOf(y to 1u) to Rational(-15, 2), + mapOf(x to 1u, y to 1u) to Rational(-13, 8), + mapOf(x to 2u, y to 1u) to Rational(-14, 3), + mapOf(y to 2u) to Rational(-7, 6), + mapOf(x to 1u, y to 2u) to Rational(7, 4), + mapOf(x to 2u, y to 2u) to Rational(9, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-7, 4), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(-16, 2), + mapOf(y to 1u) to Rational(-15, 5), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(5, 4), + mapOf(y to 2u) to Rational(-12, 5), + mapOf(x to 1u, y to 2u) to Rational(-18, 2), + mapOf(x to 2u, y to 2u) to Rational(6, 7), + ) + ), + )), + "test 4" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(2303, 64), + mapOf(x to 1u) to Rational(31843, 192), + mapOf(x to 2u) to Rational(118891, 576), + mapOf(x to 3u) to Rational(94453, 168), + mapOf(x to 4u) to Rational(-179203, 1512), + mapOf(x to 5u) to Rational(-16979, 126), + mapOf(x to 6u) to Rational(-13499, 12), + mapOf(y to 1u) to Rational(-4767, 64), + mapOf(x to 1u, y to 1u) to Rational(-58689, 256), + mapOf(x to 2u, y to 1u) to Rational(-757333, 4032), + mapOf(x to 3u, y to 1u) to Rational(-4921205, 4032), + mapOf(x to 4u, y to 1u) to Rational(-2930815, 4032), + mapOf(x to 5u, y to 1u) to Rational(-398803, 1512), + mapOf(x to 6u, y to 1u) to Rational(18835, 36), + mapOf(y to 2u) to Rational(224101, 960), + mapOf(x to 1u, y to 2u) to Rational(9139699, 40320), + mapOf(x to 2u, y to 2u) to Rational(3848803, 5760), + mapOf(x to 3u, y to 2u) to Rational(93102371, 241920), + mapOf(x to 4u, y to 2u) to Rational(-65821229, 141120), + mapOf(x to 5u, y to 2u) to Rational(-15675899, 7056), + mapOf(x to 6u, y to 2u) to Rational(10459, 189), + mapOf(y to 3u) to Rational(2411, 16), + mapOf(x to 1u, y to 3u) to Rational(1294543, 10080), + mapOf(x to 2u, y to 3u) to Rational(-1740199, 1440), + mapOf(x to 3u, y to 3u) to Rational(-266994841, 282240), + mapOf(x to 4u, y to 3u) to Rational(-41261893, 211680), + mapOf(x to 5u, y to 3u) to Rational(1717357, 3528), + mapOf(x to 6u, y to 3u) to Rational(69, 14), + mapOf(y to 4u) to Rational(13231, 360), + mapOf(x to 1u, y to 4u) to Rational(4858831, 25200), + mapOf(x to 2u, y to 4u) to Rational(15565759, 75600), + mapOf(x to 3u, y to 4u) to Rational(-15583391, 35280), + mapOf(x to 4u, y to 4u) to Rational(-13345747, 11760), + mapOf(x to 5u, y to 4u) to Rational(140103, 686), + mapOf(x to 6u, y to 4u) to Rational(-765, 49) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(31409, 576), + mapOf(x to 1u) to Rational(-337099, 1728), + mapOf(x to 2u) to Rational(-211429, 1728), + mapOf(x to 3u) to Rational(-259241, 432), + mapOf(x to 4u) to Rational(-13777, 36), + mapOf(x to 5u) to Rational(-41389, 72), + mapOf(x to 6u) to Rational(-7679, 48), + mapOf(y to 1u) to Rational(-3269, 12), + mapOf(x to 1u, y to 1u) to Rational(629569, 864), + mapOf(x to 2u, y to 1u) to Rational(53867, 324), + mapOf(x to 3u, y to 1u) to Rational(2290577, 1728), + mapOf(x to 4u, y to 1u) to Rational(101507, 216), + mapOf(x to 5u, y to 1u) to Rational(213109, 288), + mapOf(x to 6u, y to 1u) to Rational(17927, 144), + mapOf(y to 2u) to Rational(314587, 1080), + mapOf(x to 1u, y to 2u) to Rational(-109771, 144), + mapOf(x to 2u, y to 2u) to Rational(-6469, 16), + mapOf(x to 3u, y to 2u) to Rational(-298291681, 181440), + mapOf(x to 4u, y to 2u) to Rational(-59147357, 48384), + mapOf(x to 5u, y to 2u) to Rational(-4982365, 6048), + mapOf(x to 6u, y to 2u) to Rational(-18727, 576), + mapOf(y to 3u) to Rational(12379, 90), + mapOf(x to 1u, y to 3u) to Rational(-542911, 1620), + mapOf(x to 2u, y to 3u) to Rational(143123, 1260), + mapOf(x to 3u, y to 3u) to Rational(9859177, 30240), + mapOf(x to 4u, y to 3u) to Rational(9312529, 20160), + mapOf(x to 5u, y to 3u) to Rational(207001, 672), + mapOf(x to 6u, y to 3u) to Rational(203, 24), + mapOf(y to 4u) to Rational(9442, 675), + mapOf(x to 1u, y to 4u) to Rational(-13729, 300), + mapOf(x to 2u, y to 4u) to Rational(-3490471, 25200), + mapOf(x to 3u, y to 4u) to Rational(-333031, 840), + mapOf(x to 4u, y to 4u) to Rational(-7572211, 47040), + mapOf(x to 5u, y to 4u) to Rational(-1189, 56), + mapOf(x to 6u, y to 4u) to Rational(-405, 196) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + y to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(14, 4), + mapOf(x to 1u) to Rational(7, 6), + mapOf(x to 2u) to Rational(7, 2), + mapOf(y to 1u) to Rational(-15, 2), + mapOf(x to 1u, y to 1u) to Rational(-13, 8), + mapOf(x to 2u, y to 1u) to Rational(-14, 3), + mapOf(y to 2u) to Rational(-7, 6), + mapOf(x to 1u, y to 2u) to Rational(7, 4), + mapOf(x to 2u, y to 2u) to Rational(9, 7), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-7, 4), + mapOf(x to 1u) to Rational(-6, 3), + mapOf(x to 2u) to Rational(-16, 2), + mapOf(y to 1u) to Rational(-15, 5), + mapOf(x to 1u, y to 1u) to Rational(4, 6), + mapOf(x to 2u, y to 1u) to Rational(5, 4), + mapOf(y to 2u) to Rational(-12, 5), + mapOf(x to 1u, y to 2u) to Rational(-18, 2), + mapOf(x to 2u, y to 2u) to Rational(6, 7), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 8), + mapOf(x to 1u) to Rational(-12, 6), + mapOf(x to 2u) to Rational(7, 6), + mapOf(y to 1u) to Rational(-10, 4), + mapOf(x to 1u, y to 1u) to Rational(-7, 6), + mapOf(x to 2u, y to 1u) to Rational(8, 9), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(5, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(10, 6), + mapOf(x to 1u) to Rational(-18, 6), + mapOf(x to 2u) to Rational(5, 1), + mapOf(y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(8, 4), + mapOf(x to 2u, y to 1u) to Rational(-4, 9), + mapOf(y to 2u) to Rational(-6, 5), + mapOf(x to 1u, y to 2u) to Rational(-15, 8), + mapOf(x to 2u, y to 2u) to Rational(-18, 5), + ) + ), + )), + "test 4'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-506213, 2800), + mapOf(x to 1u) to Rational(9859, 315), + mapOf(x to 2u) to Rational(17384377, 11340), + mapOf(x to 3u) to Rational(-9662, 63), + mapOf(x to 4u) to Rational(-12563, 4), + mapOf(y to 1u) to Rational(-486293, 22400), + mapOf(x to 1u, y to 1u) to Rational(-6530947, 25200), + mapOf(x to 2u, y to 1u) to Rational(866125, 18144), + mapOf(x to 3u, y to 1u) to Rational(2948747, 2520), + mapOf(x to 4u, y to 1u) to Rational(1196611, 2016), + mapOf(y to 2u) to Rational(-20266021, 117600), + mapOf(x to 1u, y to 2u) to Rational(26656339, 44100), + mapOf(x to 2u, y to 2u) to Rational(19499183, 18144), + mapOf(x to 3u, y to 2u) to Rational(-19801849, 7560), + mapOf(x to 4u, y to 2u) to Rational(-2639635, 1296), + mapOf(y to 3u) to Rational(-5017697, 29400), + mapOf(x to 1u, y to 3u) to Rational(-606007, 1575), + mapOf(x to 2u, y to 3u) to Rational(127494487, 132300), + mapOf(x to 3u, y to 3u) to Rational(166567, 105), + mapOf(x to 4u, y to 3u) to Rational(486403, 18144), + mapOf(y to 4u) to Rational(-32182, 735), + mapOf(x to 1u, y to 4u) to Rational(2420671, 8820), + mapOf(x to 2u, y to 4u) to Rational(-12619193, 26460), + mapOf(x to 3u, y to 4u) to Rational(-6823067, 5670), + mapOf(x to 4u, y to 4u) to Rational(-2311693, 13608), + mapOf(y to 5u) to Rational(-13324, 245), + mapOf(x to 1u, y to 5u) to Rational(1966, 35), + mapOf(x to 2u, y to 5u) to Rational(1052719, 2520), + mapOf(x to 3u, y to 5u) to Rational(19153, 270), + mapOf(x to 4u, y to 5u) to Rational(701, 54), + mapOf(y to 6u) to Rational(4647, 196), + mapOf(x to 1u, y to 6u) to Rational(2197, 28), + mapOf(x to 2u, y to 6u) to Rational(-43853, 336), + mapOf(x to 3u, y to 6u) to Rational(-301, 3), + mapOf(x to 4u, y to 6u) to Rational(34, 3) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-2843, 1600), + mapOf(x to 1u) to Rational(-1483, 240), + mapOf(x to 2u) to Rational(110623, 1296), + mapOf(x to 3u) to Rational(1265, 72), + mapOf(x to 4u) to Rational(-5011, 16), + mapOf(y to 1u) to Rational(47743, 1800), + mapOf(x to 1u, y to 1u) to Rational(619229, 32400), + mapOf(x to 2u, y to 1u) to Rational(-5978369, 58320), + mapOf(x to 3u, y to 1u) to Rational(-86081, 1620), + mapOf(x to 4u, y to 1u) to Rational(6325, 72), + mapOf(y to 2u) to Rational(110951, 3360), + mapOf(x to 1u, y to 2u) to Rational(-9550649, 302400), + mapOf(x to 2u, y to 2u) to Rational(6542933, 85050), + mapOf(x to 3u, y to 2u) to Rational(4708291, 38880), + mapOf(x to 4u, y to 2u) to Rational(-433327, 1296), + mapOf(y to 3u) to Rational(56143, 600), + mapOf(x to 1u, y to 3u) to Rational(94243, 720), + mapOf(x to 2u, y to 3u) to Rational(-46779139, 226800), + mapOf(x to 3u, y to 3u) to Rational(-6948253, 12960), + mapOf(x to 4u, y to 3u) to Rational(-260261, 486), + mapOf(y to 4u) to Rational(-3205317, 19600), + mapOf(x to 1u, y to 4u) to Rational(-201253, 1050), + mapOf(x to 2u, y to 4u) to Rational(332192677, 302400), + mapOf(x to 3u, y to 4u) to Rational(351511, 360), + mapOf(x to 4u, y to 4u) to Rational(-40547, 81), + mapOf(y to 5u) to Rational(-65421, 1960), + mapOf(x to 1u, y to 5u) to Rational(-10118, 35), + mapOf(x to 2u, y to 5u) to Rational(-4341709, 10080), + mapOf(x to 3u, y to 5u) to Rational(-91703, 360), + mapOf(x to 4u, y to 5u) to Rational(-85, 9), + mapOf(y to 6u) to Rational(-25965, 784), + mapOf(x to 1u, y to 6u) to Rational(3351, 16), + mapOf(x to 2u, y to 6u) to Rational(595159, 1344), + mapOf(x to 3u, y to 6u) to Rational(-1381, 12), + mapOf(x to 4u, y to 6u) to Rational(-155, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-17, 5), + mapOf(x to 1u) to Rational(2, 6), + mapOf(x to 2u) to Rational(14, 1), + mapOf(y to 1u) to Rational(-6, 6), + mapOf(x to 1u, y to 1u) to Rational(-7, 3), + mapOf(x to 2u, y to 1u) to Rational(-2, 9), + mapOf(y to 2u) to Rational(-9, 6), + mapOf(x to 1u, y to 2u) to Rational(17, 4), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5, 4), + mapOf(x to 1u) to Rational(-5, 9), + mapOf(x to 2u) to Rational(-3, 6), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(14, 5), + mapOf(x to 2u, y to 1u) to Rational(5, 2), + mapOf(y to 2u) to Rational(-18, 7), + mapOf(x to 1u, y to 2u) to Rational(-8, 2), + mapOf(x to 2u, y to 2u) to Rational(18, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-506213, 2800), + mapOf(x to 1u) to Rational(9859, 315), + mapOf(x to 2u) to Rational(17384377, 11340), + mapOf(x to 3u) to Rational(-9662, 63), + mapOf(x to 4u) to Rational(-12563, 4), + mapOf(y to 1u) to Rational(-486293, 22400), + mapOf(x to 1u, y to 1u) to Rational(-6530947, 25200), + mapOf(x to 2u, y to 1u) to Rational(866125, 18144), + mapOf(x to 3u, y to 1u) to Rational(2948747, 2520), + mapOf(x to 4u, y to 1u) to Rational(1196611, 2016), + mapOf(y to 2u) to Rational(-20266021, 117600), + mapOf(x to 1u, y to 2u) to Rational(26656339, 44100), + mapOf(x to 2u, y to 2u) to Rational(19499183, 18144), + mapOf(x to 3u, y to 2u) to Rational(-19801849, 7560), + mapOf(x to 4u, y to 2u) to Rational(-2639635, 1296), + mapOf(y to 3u) to Rational(-5017697, 29400), + mapOf(x to 1u, y to 3u) to Rational(-606007, 1575), + mapOf(x to 2u, y to 3u) to Rational(127494487, 132300), + mapOf(x to 3u, y to 3u) to Rational(166567, 105), + mapOf(x to 4u, y to 3u) to Rational(486403, 18144), + mapOf(y to 4u) to Rational(-32182, 735), + mapOf(x to 1u, y to 4u) to Rational(2420671, 8820), + mapOf(x to 2u, y to 4u) to Rational(-12619193, 26460), + mapOf(x to 3u, y to 4u) to Rational(-6823067, 5670), + mapOf(x to 4u, y to 4u) to Rational(-2311693, 13608), + mapOf(y to 5u) to Rational(-13324, 245), + mapOf(x to 1u, y to 5u) to Rational(1966, 35), + mapOf(x to 2u, y to 5u) to Rational(1052719, 2520), + mapOf(x to 3u, y to 5u) to Rational(19153, 270), + mapOf(x to 4u, y to 5u) to Rational(701, 54), + mapOf(y to 6u) to Rational(4647, 196), + mapOf(x to 1u, y to 6u) to Rational(2197, 28), + mapOf(x to 2u, y to 6u) to Rational(-43853, 336), + mapOf(x to 3u, y to 6u) to Rational(-301, 3), + mapOf(x to 4u, y to 6u) to Rational(34, 3) + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-2843, 1600), + mapOf(x to 1u) to Rational(-1483, 240), + mapOf(x to 2u) to Rational(110623, 1296), + mapOf(x to 3u) to Rational(1265, 72), + mapOf(x to 4u) to Rational(-5011, 16), + mapOf(y to 1u) to Rational(47743, 1800), + mapOf(x to 1u, y to 1u) to Rational(619229, 32400), + mapOf(x to 2u, y to 1u) to Rational(-5978369, 58320), + mapOf(x to 3u, y to 1u) to Rational(-86081, 1620), + mapOf(x to 4u, y to 1u) to Rational(6325, 72), + mapOf(y to 2u) to Rational(110951, 3360), + mapOf(x to 1u, y to 2u) to Rational(-9550649, 302400), + mapOf(x to 2u, y to 2u) to Rational(6542933, 85050), + mapOf(x to 3u, y to 2u) to Rational(4708291, 38880), + mapOf(x to 4u, y to 2u) to Rational(-433327, 1296), + mapOf(y to 3u) to Rational(56143, 600), + mapOf(x to 1u, y to 3u) to Rational(94243, 720), + mapOf(x to 2u, y to 3u) to Rational(-46779139, 226800), + mapOf(x to 3u, y to 3u) to Rational(-6948253, 12960), + mapOf(x to 4u, y to 3u) to Rational(-260261, 486), + mapOf(y to 4u) to Rational(-3205317, 19600), + mapOf(x to 1u, y to 4u) to Rational(-201253, 1050), + mapOf(x to 2u, y to 4u) to Rational(332192677, 302400), + mapOf(x to 3u, y to 4u) to Rational(351511, 360), + mapOf(x to 4u, y to 4u) to Rational(-40547, 81), + mapOf(y to 5u) to Rational(-65421, 1960), + mapOf(x to 1u, y to 5u) to Rational(-10118, 35), + mapOf(x to 2u, y to 5u) to Rational(-4341709, 10080), + mapOf(x to 3u, y to 5u) to Rational(-91703, 360), + mapOf(x to 4u, y to 5u) to Rational(-85, 9), + mapOf(y to 6u) to Rational(-25965, 784), + mapOf(x to 1u, y to 6u) to Rational(3351, 16), + mapOf(x to 2u, y to 6u) to Rational(595159, 1344), + mapOf(x to 3u, y to 6u) to Rational(-1381, 12), + mapOf(x to 4u, y to 6u) to Rational(-155, 3) + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + x to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(-17, 5), + mapOf(x to 1u) to Rational(2, 6), + mapOf(x to 2u) to Rational(14, 1), + mapOf(y to 1u) to Rational(-6, 6), + mapOf(x to 1u, y to 1u) to Rational(-7, 3), + mapOf(x to 2u, y to 1u) to Rational(-2, 9), + mapOf(y to 2u) to Rational(-9, 6), + mapOf(x to 1u, y to 2u) to Rational(17, 4), + mapOf(x to 2u, y to 2u) to Rational(2, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(5, 4), + mapOf(x to 1u) to Rational(-5, 9), + mapOf(x to 2u) to Rational(-3, 6), + mapOf(y to 1u) to Rational(6, 5), + mapOf(x to 1u, y to 1u) to Rational(14, 5), + mapOf(x to 2u, y to 1u) to Rational(5, 2), + mapOf(y to 2u) to Rational(-18, 7), + mapOf(x to 1u, y to 2u) to Rational(-8, 2), + mapOf(x to 2u, y to 2u) to Rational(18, 9), + ) + ), + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 8), + mapOf(x to 1u) to Rational(-12, 6), + mapOf(x to 2u) to Rational(7, 6), + mapOf(y to 1u) to Rational(-10, 4), + mapOf(x to 1u, y to 1u) to Rational(-7, 6), + mapOf(x to 2u, y to 1u) to Rational(8, 9), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(5, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(10, 6), + mapOf(x to 1u) to Rational(-18, 6), + mapOf(x to 2u) to Rational(5, 1), + mapOf(y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(8, 4), + mapOf(x to 2u, y to 1u) to Rational(-4, 9), + mapOf(y to 2u) to Rational(-6, 5), + mapOf(x to 1u, y to 2u) to Rational(-15, 8), + mapOf(x to 2u, y to 2u) to Rational(-18, 5), + ) + ), + )), + "test 5'" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ), + LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(10, 2), + mapOf(x to 1u) to Rational(6, 7), + mapOf(x to 2u) to Rational(-16, 1), + mapOf(y to 1u) to Rational(13, 8), + mapOf(x to 1u, y to 1u) to Rational(-12, 1), + mapOf(x to 2u, y to 1u) to Rational(16, 8), + mapOf(y to 2u) to Rational(10, 4), + mapOf(x to 1u, y to 2u) to Rational(4, 1), + mapOf(x to 2u, y to 2u) to Rational(-11, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1, 4), + mapOf(x to 1u) to Rational(-17, 4), + mapOf(x to 2u) to Rational(-14, 8), + mapOf(y to 1u) to Rational(17, 9), + mapOf(x to 1u, y to 1u) to Rational(1, 3), + mapOf(x to 2u, y to 1u) to Rational(7, 6), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-17, 1), + mapOf(x to 2u, y to 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + iota to LabeledRationalFunction( + LabeledPolynomialAsIs( + mapOf() to Rational(5, 8), + mapOf(x to 1u) to Rational(-12, 6), + mapOf(x to 2u) to Rational(7, 6), + mapOf(y to 1u) to Rational(-10, 4), + mapOf(x to 1u, y to 1u) to Rational(-7, 6), + mapOf(x to 2u, y to 1u) to Rational(8, 9), + mapOf(y to 2u) to Rational(16, 3), + mapOf(x to 1u, y to 2u) to Rational(-13, 4), + mapOf(x to 2u, y to 2u) to Rational(5, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(10, 6), + mapOf(x to 1u) to Rational(-18, 6), + mapOf(x to 2u) to Rational(5, 1), + mapOf(y to 1u) to Rational(17, 7), + mapOf(x to 1u, y to 1u) to Rational(8, 4), + mapOf(x to 2u, y to 1u) to Rational(-4, 9), + mapOf(y to 2u) to Rational(-6, 5), + mapOf(x to 1u, y to 2u) to Rational(-15, 8), + mapOf(x to 2u, y to 2u) to Rational(-18, 5), + ) + ), + )), + "test 6'" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_derivativeWithRespectTo_variable() { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2), + mapOf(x to 1u) to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).derivativeWithRespectTo(RationalField, x), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 3), + mapOf(x to 1u) to Rational(1, 1), + mapOf(x to 2u) to Rational(-33, 8), + mapOf(x to 3u) to Rational(72, 1), + mapOf(y to 1u) to Rational(2, 3), + mapOf(x to 1u, y to 1u) to Rational(-22, 1), + mapOf(x to 2u, y to 1u) to Rational(-1, 1), + mapOf(x to 3u, y to 1u) to Rational(-36, 1), + mapOf(y to 2u) to Rational(-8, 5), + mapOf(x to 1u, y to 2u) to Rational(-1, 4), + mapOf(x to 2u, y to 2u) to Rational(12, 7), + mapOf(x to 3u, y to 2u) to Rational(-2, 1), + mapOf(y to 3u) to Rational(16, 8), + mapOf(x to 1u, y to 3u) to Rational(-4, 1), + mapOf(x to 2u, y to 3u) to Rational(9, 2), + mapOf(x to 3u, y to 3u) to Rational(20, 9), + mapOf(y to 4u) to Rational(-10, 1), + mapOf(x to 1u, y to 4u) to Rational(-14, 1), + mapOf(x to 2u, y to 4u) to Rational(3, 7), + mapOf(x to 3u, y to 4u) to Rational(20, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, x), + "test 2a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-18, 3), + mapOf(x to 1u) to Rational(2, 3), + mapOf(x to 2u) to Rational(-11, 1), + mapOf(x to 3u) to Rational(-1, 3), + mapOf(x to 4u) to Rational(-18, 2), + mapOf(y to 1u) to Rational(-20, 3), + mapOf(x to 1u, y to 1u) to Rational(-16, 5), + mapOf(x to 2u, y to 1u) to Rational(-1, 4), + mapOf(x to 3u, y to 1u) to Rational(8, 7), + mapOf(x to 4u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(9, 7), + mapOf(x to 1u, y to 2u) to Rational(6, 1), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(x to 3u, y to 2u) to Rational(9, 2), + mapOf(x to 4u, y to 2u) to Rational(5, 3), + mapOf(y to 3u) to Rational(-9, 1), + mapOf(x to 1u, y to 3u) to Rational(-40, 1), + mapOf(x to 2u, y to 3u) to Rational(-28, 1), + mapOf(x to 3u, y to 3u) to Rational(4, 7), + mapOf(x to 4u, y to 3u) to Rational(20, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, y), + "test 2b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(-1, 4), + mapOf(x to 2u, y to 2u) to Rational(12, 7), + mapOf(x to 3u, y to 2u) to Rational(-2, 1), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(-4, 1), + mapOf(x to 2u, y to 3u) to Rational(9, 2), + mapOf(x to 3u, y to 3u) to Rational(20, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(-14, 1), + mapOf(x to 2u, y to 4u) to Rational(3, 7), + mapOf(x to 3u, y to 4u) to Rational(20, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, x), + "test 3a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(-1, 4), + mapOf(x to 3u, y to 1u) to Rational(8, 7), + mapOf(x to 4u, y to 1u) to Rational(-1, 1), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(x to 3u, y to 2u) to Rational(9, 2), + mapOf(x to 4u, y to 2u) to Rational(5, 3), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-28, 1), + mapOf(x to 3u, y to 3u) to Rational(4, 7), + mapOf(x to 4u, y to 3u) to Rational(20, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, y), + "test 3b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2, 3), + mapOf(x to 1u) to Rational(1, 1), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(y to 1u) to Rational(2, 3), + mapOf(x to 1u, y to 1u) to Rational(-22, 1), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-8, 5), + mapOf(x to 1u, y to 2u) to Rational(-1, 4), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).derivativeWithRespectTo(RationalField, x), + "test 4a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-18, 3), + mapOf(x to 1u) to Rational(2, 3), + mapOf(x to 2u) to Rational(-11, 1), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-20, 3), + mapOf(x to 1u, y to 1u) to Rational(-16, 5), + mapOf(x to 2u, y to 1u) to Rational(-1, 4), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).derivativeWithRespectTo(RationalField, y), + "test 4b" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, iota), + "test 5" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthDerivativeWithRespectTo_variable_order() { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2), + mapOf(x to 1u) to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, x, 1u), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, x, 0u), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, x, 2u), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, x, 3u), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, x, 4u), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, y, 0u), + "test 6" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, y, 1u), + "test 7" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, y, 2u), + "test 8" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1, 1), + mapOf(x to 1u) to Rational(-33, 4), + mapOf(x to 2u) to Rational(216, 1), + mapOf(y to 1u) to Rational(-22, 1), + mapOf(x to 1u, y to 1u) to Rational(-2, 1), + mapOf(x to 2u, y to 1u) to Rational(-108, 1), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(24, 7), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(y to 3u) to Rational(-4, 1), + mapOf(x to 1u, y to 3u) to Rational(9, 1), + mapOf(x to 2u, y to 3u) to Rational(20, 3), + mapOf(y to 4u) to Rational(-14, 1), + mapOf(x to 1u, y to 4u) to Rational(6, 7), + mapOf(x to 2u, y to 4u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, x, 2u), + "test 9a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-20, 3), + mapOf(x to 1u) to Rational(-16, 5), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(8, 7), + mapOf(x to 4u) to Rational(-1, 1), + mapOf(y to 1u) to Rational(18, 7), + mapOf(x to 1u, y to 1u) to Rational(12, 1), + mapOf(x to 2u, y to 1u) to Rational(-12, 1), + mapOf(x to 3u, y to 1u) to Rational(9, 1), + mapOf(x to 4u, y to 1u) to Rational(10, 3), + mapOf(y to 2u) to Rational(-27, 1), + mapOf(x to 1u, y to 2u) to Rational(-120, 1), + mapOf(x to 2u, y to 2u) to Rational(-84, 1), + mapOf(x to 3u, y to 2u) to Rational(12, 7), + mapOf(x to 4u, y to 2u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, y, 2u), + "test 9b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(24, 7), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(y to 3u) to Rational(-4, 1), + mapOf(x to 1u, y to 3u) to Rational(9, 1), + mapOf(x to 2u, y to 3u) to Rational(20, 3), + mapOf(y to 4u) to Rational(-14, 1), + mapOf(x to 1u, y to 4u) to Rational(6, 7), + mapOf(x to 2u, y to 4u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, x, 2u), + "test 10a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(8, 7), + mapOf(x to 4u) to Rational(-1, 1), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(-12, 1), + mapOf(x to 3u, y to 1u) to Rational(9, 1), + mapOf(x to 4u, y to 1u) to Rational(10, 3), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-84, 1), + mapOf(x to 3u, y to 2u) to Rational(12, 7), + mapOf(x to 4u, y to 2u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, y, 2u), + "test 10b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1, 1), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(y to 1u) to Rational(-22, 1), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, x, 2u), + "test 11a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-20, 3), + mapOf(x to 1u) to Rational(-16, 5), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, y, 2u), + "test 11b" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthDerivativeWithRespectTo_variablesAndOrders() { + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2), + mapOf(x to 1u) to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 1u)), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 0u)), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 3u)), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 4u)), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 0u)), + "test 6" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 1u)), + "test 7" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 8" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf()), + "test 9" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-2), + mapOf(x to 1u) to Rational(2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf( + x to 1u, + y to 0u + )), + "test 10" + ) + assertEquals( + LabeledPolynomialAsIs(), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf( + x to 0u, + y to 1u + )), + "test 11" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1, 1), + mapOf(x to 1u) to Rational(-33, 4), + mapOf(x to 2u) to Rational(216, 1), + mapOf(y to 1u) to Rational(-22, 1), + mapOf(x to 1u, y to 1u) to Rational(-2, 1), + mapOf(x to 2u, y to 1u) to Rational(-108, 1), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(24, 7), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(y to 3u) to Rational(-4, 1), + mapOf(x to 1u, y to 3u) to Rational(9, 1), + mapOf(x to 2u, y to 3u) to Rational(20, 3), + mapOf(y to 4u) to Rational(-14, 1), + mapOf(x to 1u, y to 4u) to Rational(6, 7), + mapOf(x to 2u, y to 4u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 12a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(2, 3), + mapOf(x to 1u) to Rational(-22, 1), + mapOf(x to 2u) to Rational(-1, 1), + mapOf(x to 3u) to Rational(-36, 1), + mapOf(y to 1u) to Rational(-16, 5), + mapOf(x to 1u, y to 1u) to Rational(-1, 2), + mapOf(x to 2u, y to 1u) to Rational(24, 7), + mapOf(x to 3u, y to 1u) to Rational(-4, 1), + mapOf(y to 2u) to Rational(6, 1), + mapOf(x to 1u, y to 2u) to Rational(-12, 1), + mapOf(x to 2u, y to 2u) to Rational(27, 2), + mapOf(x to 3u, y to 2u) to Rational(20, 3), + mapOf(y to 3u) to Rational(-40, 1), + mapOf(x to 1u, y to 3u) to Rational(-56, 1), + mapOf(x to 2u, y to 3u) to Rational(12, 7), + mapOf(x to 3u, y to 3u) to Rational(80, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 12b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-20, 3), + mapOf(x to 1u) to Rational(-16, 5), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(8, 7), + mapOf(x to 4u) to Rational(-1, 1), + mapOf(y to 1u) to Rational(18, 7), + mapOf(x to 1u, y to 1u) to Rational(12, 1), + mapOf(x to 2u, y to 1u) to Rational(-12, 1), + mapOf(x to 3u, y to 1u) to Rational(9, 1), + mapOf(x to 4u, y to 1u) to Rational(10, 3), + mapOf(y to 2u) to Rational(-27, 1), + mapOf(x to 1u, y to 2u) to Rational(-120, 1), + mapOf(x to 2u, y to 2u) to Rational(-84, 1), + mapOf(x to 3u, y to 2u) to Rational(12, 7), + mapOf(x to 4u, y to 2u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 12c" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(24, 7), + mapOf(x to 2u, y to 2u) to Rational(-6, 1), + mapOf(y to 3u) to Rational(-4, 1), + mapOf(x to 1u, y to 3u) to Rational(9, 1), + mapOf(x to 2u, y to 3u) to Rational(20, 3), + mapOf(y to 4u) to Rational(-14, 1), + mapOf(x to 1u, y to 4u) to Rational(6, 7), + mapOf(x to 2u, y to 4u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 13a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(-1, 2), + mapOf(x to 2u, y to 1u) to Rational(24, 7), + mapOf(x to 3u, y to 1u) to Rational(-4, 1), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(-12, 1), + mapOf(x to 2u, y to 2u) to Rational(27, 2), + mapOf(x to 3u, y to 2u) to Rational(20, 3), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(-56, 1), + mapOf(x to 2u, y to 3u) to Rational(12, 7), + mapOf(x to 3u, y to 3u) to Rational(80, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 13b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(8, 7), + mapOf(x to 4u) to Rational(-1, 1), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(-12, 1), + mapOf(x to 3u, y to 1u) to Rational(9, 1), + mapOf(x to 4u, y to 1u) to Rational(10, 3), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-84, 1), + mapOf(x to 3u, y to 2u) to Rational(12, 7), + mapOf(x to 4u, y to 2u) to Rational(60, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 13c" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1, 1), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(y to 1u) to Rational(-22, 1), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-1, 4), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 14a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(2, 3), + mapOf(x to 1u) to Rational(-22, 1), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(y to 1u) to Rational(-16, 5), + mapOf(x to 1u, y to 1u) to Rational(-1, 2), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 14b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(-20, 3), + mapOf(x to 1u) to Rational(-16, 5), + mapOf(x to 2u) to Rational(-1, 4), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 14c" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_antiderivativeWithRespectTo_variable() { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(x to 2u) to Rational(-1), + mapOf(x to 3u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).antiderivativeWithRespectTo(RationalField, x), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-6, 8), + mapOf(x to 2u) to Rational(-1, 3), + mapOf(x to 3u) to Rational(1, 6), + mapOf(x to 4u) to Rational(-11, 32), + mapOf(x to 5u) to Rational(18, 5), + mapOf(x to 1u, y to 1u) to Rational(-18, 3), + mapOf(x to 2u, y to 1u) to Rational(1, 3), + mapOf(x to 3u, y to 1u) to Rational(-11, 3), + mapOf(x to 4u, y to 1u) to Rational(-1, 12), + mapOf(x to 5u, y to 1u) to Rational(-18, 10), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(-4, 5), + mapOf(x to 3u, y to 2u) to Rational(-1, 24), + mapOf(x to 4u, y to 2u) to Rational(1, 7), + mapOf(x to 5u, y to 2u) to Rational(-1, 10), + mapOf(x to 1u, y to 3u) to Rational(3, 7), + mapOf(x to 2u, y to 3u) to Rational(1, 1), + mapOf(x to 3u, y to 3u) to Rational(-2, 3), + mapOf(x to 4u, y to 3u) to Rational(3, 8), + mapOf(x to 5u, y to 3u) to Rational(1, 9), + mapOf(x to 1u, y to 4u) to Rational(-18, 8), + mapOf(x to 2u, y to 4u) to Rational(-5, 1), + mapOf(x to 3u, y to 4u) to Rational(-7, 3), + mapOf(x to 4u, y to 4u) to Rational(1, 28), + mapOf(x to 5u, y to 4u) to Rational(1, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, x), + "test 2a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(-6, 8), + mapOf(x to 1u, y to 1u) to Rational(-2, 3), + mapOf(x to 2u, y to 1u) to Rational(1, 2), + mapOf(x to 3u, y to 1u) to Rational(-11, 8), + mapOf(x to 4u, y to 1u) to Rational(18, 1), + mapOf(y to 2u) to Rational(-9, 3), + mapOf(x to 1u, y to 2u) to Rational(1, 3), + mapOf(x to 2u, y to 2u) to Rational(-11, 2), + mapOf(x to 3u, y to 2u) to Rational(-1, 6), + mapOf(x to 4u, y to 2u) to Rational(-9, 2), + mapOf(y to 3u) to Rational(-10, 9), + mapOf(x to 1u, y to 3u) to Rational(-8, 15), + mapOf(x to 2u, y to 3u) to Rational(-1, 24), + mapOf(x to 3u, y to 3u) to Rational(4, 21), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(y to 4u) to Rational(3, 28), + mapOf(x to 1u, y to 4u) to Rational(1, 2), + mapOf(x to 2u, y to 4u) to Rational(-1, 2), + mapOf(x to 3u, y to 4u) to Rational(3, 8), + mapOf(x to 4u, y to 4u) to Rational(5, 36), + mapOf(y to 5u) to Rational(-9, 20), + mapOf(x to 1u, y to 5u) to Rational(-2, 1), + mapOf(x to 2u, y to 5u) to Rational(-7, 5), + mapOf(x to 3u, y to 5u) to Rational(1, 35), + mapOf(x to 4u, y to 5u) to Rational(1, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, y), + "test 2b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(-1, 24), + mapOf(x to 4u, y to 2u) to Rational(1, 7), + mapOf(x to 5u, y to 2u) to Rational(-1, 10), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(-2, 3), + mapOf(x to 4u, y to 3u) to Rational(3, 8), + mapOf(x to 5u, y to 3u) to Rational(1, 9), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(-7, 3), + mapOf(x to 4u, y to 4u) to Rational(1, 28), + mapOf(x to 5u, y to 4u) to Rational(1, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, x), + "test 3a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-1, 24), + mapOf(x to 3u, y to 3u) to Rational(4, 21), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-1, 2), + mapOf(x to 3u, y to 4u) to Rational(3, 8), + mapOf(x to 4u, y to 4u) to Rational(5, 36), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(-7, 5), + mapOf(x to 3u, y to 5u) to Rational(1, 35), + mapOf(x to 4u, y to 5u) to Rational(1, 1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, y), + "test 3b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-6, 8), + mapOf(x to 2u) to Rational(-1, 3), + mapOf(x to 3u) to Rational(1, 6), + mapOf(x to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(-18, 3), + mapOf(x to 2u, y to 1u) to Rational(1, 3), + mapOf(x to 3u, y to 1u) to Rational(-11, 3), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(-10, 3), + mapOf(x to 2u, y to 2u) to Rational(-4, 5), + mapOf(x to 3u, y to 2u) to Rational(-1, 24), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(x to 5u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(x to 5u, y to 3u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(x to 5u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).antiderivativeWithRespectTo(RationalField, x), + "test 4a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(-6, 8), + mapOf(x to 1u, y to 1u) to Rational(-2, 3), + mapOf(x to 2u, y to 1u) to Rational(1, 2), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-9, 3), + mapOf(x to 1u, y to 2u) to Rational(1, 3), + mapOf(x to 2u, y to 2u) to Rational(-11, 2), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(-10, 9), + mapOf(x to 1u, y to 3u) to Rational(-8, 15), + mapOf(x to 2u, y to 3u) to Rational(-1, 24), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(0), + mapOf(x to 3u, y to 5u) to Rational(0), + mapOf(x to 4u, y to 5u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).antiderivativeWithRespectTo(RationalField, y), + "test 4b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(iota to 1u) to Rational(-6, 8), + mapOf(x to 1u, iota to 1u) to Rational(-2, 3), + mapOf(x to 2u, iota to 1u) to Rational(1, 2), + mapOf(x to 3u, iota to 1u) to Rational(-11, 8), + mapOf(x to 4u, iota to 1u) to Rational(18, 1), + mapOf(y to 1u, iota to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u, iota to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u, iota to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u, iota to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u, iota to 1u) to Rational(-18, 2), + mapOf(y to 2u, iota to 1u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u, iota to 1u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u, iota to 1u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u, iota to 1u) to Rational(4, 7), + mapOf(x to 4u, y to 2u, iota to 1u) to Rational(-4, 8), + mapOf(y to 3u, iota to 1u) to Rational(3, 7), + mapOf(x to 1u, y to 3u, iota to 1u) to Rational(16, 8), + mapOf(x to 2u, y to 3u, iota to 1u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u, iota to 1u) to Rational(12, 8), + mapOf(x to 4u, y to 3u, iota to 1u) to Rational(5, 9), + mapOf(y to 4u, iota to 1u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u, iota to 1u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u, iota to 1u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u, iota to 1u) to Rational(1, 7), + mapOf(x to 4u, y to 4u, iota to 1u) to Rational(15, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, iota), + "test 5" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthAntiderivativeWithRespectTo_variable_order() { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(x to 2u) to Rational(-1), + mapOf(x to 3u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 1u), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 0u), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-1, 3), + mapOf(x to 4u) to Rational(1, 12), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 2u), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 3u) to Rational(1, 6), + mapOf(x to 4u) to Rational(-1, 12), + mapOf(x to 5u) to Rational(1, 60), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 3u), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(-1, 60), + mapOf(x to 6u) to Rational(1, 360), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 4u), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 0u), + "test 6" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(1), + mapOf(x to 1u, y to 1u) to Rational(-2), + mapOf(x to 2u, y to 1u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 1u), + "test 7" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(1, 2), + mapOf(x to 1u, y to 2u) to Rational(-1), + mapOf(x to 2u, y to 2u) to Rational(1, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 2u), + "test 8" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(-3, 8), + mapOf(x to 3u) to Rational(-1, 9), + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(-11, 160), + mapOf(x to 6u) to Rational(3, 5), + mapOf(x to 2u, y to 1u) to Rational(-9, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 9), + mapOf(x to 4u, y to 1u) to Rational(-11, 12), + mapOf(x to 5u, y to 1u) to Rational(-1, 60), + mapOf(x to 6u, y to 1u) to Rational(-3, 10), + mapOf(x to 2u, y to 2u) to Rational(-5, 3), + mapOf(x to 3u, y to 2u) to Rational(-4, 15), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(1, 35), + mapOf(x to 6u, y to 2u) to Rational(-1, 60), + mapOf(x to 2u, y to 3u) to Rational(3, 14), + mapOf(x to 3u, y to 3u) to Rational(1, 3), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(x to 5u, y to 3u) to Rational(3, 40), + mapOf(x to 6u, y to 3u) to Rational(1, 54), + mapOf(x to 2u, y to 4u) to Rational(-9, 8), + mapOf(x to 3u, y to 4u) to Rational(-5, 3), + mapOf(x to 4u, y to 4u) to Rational(-7, 12), + mapOf(x to 5u, y to 4u) to Rational(1, 140), + mapOf(x to 6u, y to 4u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, x, 2u), + "test 9a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(-3, 8), + mapOf(x to 1u, y to 2u) to Rational(-1, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 4), + mapOf(x to 3u, y to 2u) to Rational(-11, 16), + mapOf(x to 4u, y to 2u) to Rational(9, 1), + mapOf(y to 3u) to Rational(-1, 1), + mapOf(x to 1u, y to 3u) to Rational(1, 9), + mapOf(x to 2u, y to 3u) to Rational(-11, 6), + mapOf(x to 3u, y to 3u) to Rational(-1, 18), + mapOf(x to 4u, y to 3u) to Rational(-9, 6), + mapOf(y to 4u) to Rational(-5, 18), + mapOf(x to 1u, y to 4u) to Rational(-2, 15), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(1, 21), + mapOf(x to 4u, y to 4u) to Rational(-1, 24), + mapOf(y to 5u) to Rational(3, 140), + mapOf(x to 1u, y to 5u) to Rational(1, 10), + mapOf(x to 2u, y to 5u) to Rational(-1, 10), + mapOf(x to 3u, y to 5u) to Rational(3, 40), + mapOf(x to 4u, y to 5u) to Rational(1, 36), + mapOf(y to 6u) to Rational(-3, 40), + mapOf(x to 1u, y to 6u) to Rational(-1, 3), + mapOf(x to 2u, y to 6u) to Rational(-7, 30), + mapOf(x to 3u, y to 6u) to Rational(1, 210), + mapOf(x to 4u, y to 6u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, y, 2u), + "test 9b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + mapOf(x to 6u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 6u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(1, 35), + mapOf(x to 6u, y to 2u) to Rational(-1, 60), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(x to 5u, y to 3u) to Rational(3, 40), + mapOf(x to 6u, y to 3u) to Rational(1, 54), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(-7, 12), + mapOf(x to 5u, y to 4u) to Rational(1, 140), + mapOf(x to 6u, y to 4u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, x, 2u), + "test 10a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(1, 21), + mapOf(x to 4u, y to 4u) to Rational(-1, 24), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(-1, 10), + mapOf(x to 3u, y to 5u) to Rational(3, 40), + mapOf(x to 4u, y to 5u) to Rational(1, 36), + mapOf(y to 6u) to Rational(0), + mapOf(x to 1u, y to 6u) to Rational(0), + mapOf(x to 2u, y to 6u) to Rational(-7, 30), + mapOf(x to 3u, y to 6u) to Rational(1, 210), + mapOf(x to 4u, y to 6u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, y, 2u), + "test 10b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(-3, 8), + mapOf(x to 3u) to Rational(-1, 9), + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(0), + mapOf(x to 6u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(-9, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 9), + mapOf(x to 4u, y to 1u) to Rational(-11, 12), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 6u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-5, 3), + mapOf(x to 3u, y to 2u) to Rational(-4, 15), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(0), + mapOf(x to 6u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(x to 5u, y to 3u) to Rational(0), + mapOf(x to 6u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(x to 5u, y to 4u) to Rational(0), + mapOf(x to 6u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, x, 2u), + "test 11a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(-3, 8), + mapOf(x to 1u, y to 2u) to Rational(-1, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 4), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(-1, 1), + mapOf(x to 1u, y to 3u) to Rational(1, 9), + mapOf(x to 2u, y to 3u) to Rational(-11, 6), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(-5, 18), + mapOf(x to 1u, y to 4u) to Rational(-2, 15), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(0), + mapOf(x to 3u, y to 5u) to Rational(0), + mapOf(x to 4u, y to 5u) to Rational(0), + mapOf(y to 6u) to Rational(0), + mapOf(x to 1u, y to 6u) to Rational(0), + mapOf(x to 2u, y to 6u) to Rational(0), + mapOf(x to 3u, y to 6u) to Rational(0), + mapOf(x to 4u, y to 6u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, y, 2u), + "test 11b" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthAntiderivativeWithRespectTo_variablesAndOrders() { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(x to 2u) to Rational(-1), + mapOf(x to 3u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 1u)), + "test 1" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 0u), + "test 2" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-1, 3), + mapOf(x to 4u) to Rational(1, 12), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 2u), + "test 3" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 3u) to Rational(1, 6), + mapOf(x to 4u) to Rational(-1, 12), + mapOf(x to 5u) to Rational(1, 60), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 3u), + "test 4" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(-1, 60), + mapOf(x to 6u) to Rational(1, 360), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, x, 4u), + "test 5" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 0u), + "test 6" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(1), + mapOf(x to 1u, y to 1u) to Rational(-2), + mapOf(x to 2u, y to 1u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 1u), + "test 7" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(1, 2), + mapOf(x to 1u, y to 2u) to Rational(-1), + mapOf(x to 2u, y to 2u) to Rational(1, 2), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, y, 2u), + "test 8" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf()), + "test 9" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + mapOf(x to 2u) to Rational(-1), + mapOf(x to 3u) to Rational(1, 3), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf( + x to 1u, + y to 0u + )), + "test 10" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 1u) to Rational(1), + mapOf(x to 1u, y to 1u) to Rational(-2), + mapOf(x to 2u, y to 1u) to Rational(1), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(1), + mapOf(x to 1u) to Rational(-2), + mapOf(x to 2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf( + x to 0u, + y to 1u + )), + "test 11" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(-3, 8), + mapOf(x to 3u) to Rational(-1, 9), + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(-11, 160), + mapOf(x to 6u) to Rational(3, 5), + mapOf(x to 2u, y to 1u) to Rational(-9, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 9), + mapOf(x to 4u, y to 1u) to Rational(-11, 12), + mapOf(x to 5u, y to 1u) to Rational(-1, 60), + mapOf(x to 6u, y to 1u) to Rational(-3, 10), + mapOf(x to 2u, y to 2u) to Rational(-5, 3), + mapOf(x to 3u, y to 2u) to Rational(-4, 15), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(1, 35), + mapOf(x to 6u, y to 2u) to Rational(-1, 60), + mapOf(x to 2u, y to 3u) to Rational(3, 14), + mapOf(x to 3u, y to 3u) to Rational(1, 3), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(x to 5u, y to 3u) to Rational(3, 40), + mapOf(x to 6u, y to 3u) to Rational(1, 54), + mapOf(x to 2u, y to 4u) to Rational(-9, 8), + mapOf(x to 3u, y to 4u) to Rational(-5, 3), + mapOf(x to 4u, y to 4u) to Rational(-7, 12), + mapOf(x to 5u, y to 4u) to Rational(1, 140), + mapOf(x to 6u, y to 4u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 12a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u, y to 1u) to Rational(-6, 8), + mapOf(x to 2u, y to 1u) to Rational(-1, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 6), + mapOf(x to 4u, y to 1u) to Rational(-11, 32), + mapOf(x to 5u, y to 1u) to Rational(18, 5), + mapOf(x to 1u, y to 2u) to Rational(-9, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 6), + mapOf(x to 3u, y to 2u) to Rational(-11, 6), + mapOf(x to 4u, y to 2u) to Rational(-1, 24), + mapOf(x to 5u, y to 2u) to Rational(-9, 10), + mapOf(x to 1u, y to 3u) to Rational(-10, 9), + mapOf(x to 2u, y to 3u) to Rational(-4, 15), + mapOf(x to 3u, y to 3u) to Rational(-1, 72), + mapOf(x to 4u, y to 3u) to Rational(1, 21), + mapOf(x to 5u, y to 3u) to Rational(-1, 30), + mapOf(x to 1u, y to 4u) to Rational(3, 28), + mapOf(x to 2u, y to 4u) to Rational(1, 4), + mapOf(x to 3u, y to 4u) to Rational(-1, 6), + mapOf(x to 4u, y to 4u) to Rational(3, 32), + mapOf(x to 5u, y to 4u) to Rational(1, 36), + mapOf(x to 1u, y to 5u) to Rational(-9, 20), + mapOf(x to 2u, y to 5u) to Rational(-1, 1), + mapOf(x to 3u, y to 5u) to Rational(-7, 15), + mapOf(x to 4u, y to 5u) to Rational(1, 140), + mapOf(x to 5u, y to 5u) to Rational(1, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 12b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(-3, 8), + mapOf(x to 1u, y to 2u) to Rational(-1, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 4), + mapOf(x to 3u, y to 2u) to Rational(-11, 16), + mapOf(x to 4u, y to 2u) to Rational(9, 1), + mapOf(y to 3u) to Rational(-1, 1), + mapOf(x to 1u, y to 3u) to Rational(1, 9), + mapOf(x to 2u, y to 3u) to Rational(-11, 6), + mapOf(x to 3u, y to 3u) to Rational(-1, 18), + mapOf(x to 4u, y to 3u) to Rational(-9, 6), + mapOf(y to 4u) to Rational(-5, 18), + mapOf(x to 1u, y to 4u) to Rational(-2, 15), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(1, 21), + mapOf(x to 4u, y to 4u) to Rational(-1, 24), + mapOf(y to 5u) to Rational(3, 140), + mapOf(x to 1u, y to 5u) to Rational(1, 10), + mapOf(x to 2u, y to 5u) to Rational(-1, 10), + mapOf(x to 3u, y to 5u) to Rational(3, 40), + mapOf(x to 4u, y to 5u) to Rational(1, 36), + mapOf(y to 6u) to Rational(-3, 40), + mapOf(x to 1u, y to 6u) to Rational(-1, 3), + mapOf(x to 2u, y to 6u) to Rational(-7, 30), + mapOf(x to 3u, y to 6u) to Rational(1, 210), + mapOf(x to 4u, y to 6u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(-11, 8), + mapOf(x to 4u) to Rational(18, 1), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(-1, 3), + mapOf(x to 4u, y to 1u) to Rational(-18, 2), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(3, 7), + mapOf(x to 1u, y to 3u) to Rational(16, 8), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(-18, 8), + mapOf(x to 1u, y to 4u) to Rational(-10, 1), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 12c" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(x to 5u) to Rational(0), + mapOf(x to 6u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 6u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(1, 35), + mapOf(x to 6u, y to 2u) to Rational(-1, 60), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(-1, 6), + mapOf(x to 5u, y to 3u) to Rational(3, 40), + mapOf(x to 6u, y to 3u) to Rational(1, 54), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(-7, 12), + mapOf(x to 5u, y to 4u) to Rational(1, 140), + mapOf(x to 6u, y to 4u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 13a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(x to 5u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(-1, 72), + mapOf(x to 4u, y to 3u) to Rational(1, 21), + mapOf(x to 5u, y to 3u) to Rational(-1, 30), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(-1, 6), + mapOf(x to 4u, y to 4u) to Rational(3, 32), + mapOf(x to 5u, y to 4u) to Rational(1, 36), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(0), + mapOf(x to 3u, y to 5u) to Rational(-7, 15), + mapOf(x to 4u, y to 5u) to Rational(1, 140), + mapOf(x to 5u, y to 5u) to Rational(1, 5), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 13b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(0), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(1, 21), + mapOf(x to 4u, y to 4u) to Rational(-1, 24), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(-1, 10), + mapOf(x to 3u, y to 5u) to Rational(3, 40), + mapOf(x to 4u, y to 5u) to Rational(1, 36), + mapOf(y to 6u) to Rational(0), + mapOf(x to 1u, y to 6u) to Rational(0), + mapOf(x to 2u, y to 6u) to Rational(-7, 30), + mapOf(x to 3u, y to 6u) to Rational(1, 210), + mapOf(x to 4u, y to 6u) to Rational(1, 6), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(0), + mapOf(x to 1u) to Rational(0), + mapOf(x to 2u) to Rational(0), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(0), + mapOf(x to 1u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(0), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(4, 7), + mapOf(x to 4u, y to 2u) to Rational(-4, 8), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(-16, 8), + mapOf(x to 3u, y to 3u) to Rational(12, 8), + mapOf(x to 4u, y to 3u) to Rational(5, 9), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(-14, 2), + mapOf(x to 3u, y to 4u) to Rational(1, 7), + mapOf(x to 4u, y to 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 13c" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 2u) to Rational(-3, 8), + mapOf(x to 3u) to Rational(-1, 9), + mapOf(x to 4u) to Rational(1, 24), + mapOf(x to 5u) to Rational(0), + mapOf(x to 6u) to Rational(0), + mapOf(x to 2u, y to 1u) to Rational(-9, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 9), + mapOf(x to 4u, y to 1u) to Rational(-11, 12), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 6u, y to 1u) to Rational(0), + mapOf(x to 2u, y to 2u) to Rational(-5, 3), + mapOf(x to 3u, y to 2u) to Rational(-4, 15), + mapOf(x to 4u, y to 2u) to Rational(-1, 96), + mapOf(x to 5u, y to 2u) to Rational(0), + mapOf(x to 6u, y to 2u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(x to 5u, y to 3u) to Rational(0), + mapOf(x to 6u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(x to 5u, y to 4u) to Rational(0), + mapOf(x to 6u, y to 4u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 2u)), + "test 14a" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u, y to 1u) to Rational(-6, 8), + mapOf(x to 2u, y to 1u) to Rational(-1, 3), + mapOf(x to 3u, y to 1u) to Rational(1, 6), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(x to 5u, y to 1u) to Rational(0), + mapOf(x to 1u, y to 2u) to Rational(-9, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 6), + mapOf(x to 3u, y to 2u) to Rational(-11, 6), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(x to 5u, y to 2u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(-10, 9), + mapOf(x to 2u, y to 3u) to Rational(-4, 15), + mapOf(x to 3u, y to 3u) to Rational(-1, 72), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(x to 5u, y to 3u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(x to 5u, y to 4u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(0), + mapOf(x to 3u, y to 5u) to Rational(0), + mapOf(x to 4u, y to 5u) to Rational(0), + mapOf(x to 5u, y to 5u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(x to 1u, y to 1u)), + "test 14b" + ) + assertEquals( + LabeledPolynomialAsIs( + mapOf(y to 2u) to Rational(-3, 8), + mapOf(x to 1u, y to 2u) to Rational(-1, 3), + mapOf(x to 2u, y to 2u) to Rational(1, 4), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(-1, 1), + mapOf(x to 1u, y to 3u) to Rational(1, 9), + mapOf(x to 2u, y to 3u) to Rational(-11, 6), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(-5, 18), + mapOf(x to 1u, y to 4u) to Rational(-2, 15), + mapOf(x to 2u, y to 4u) to Rational(-1, 96), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + mapOf(y to 5u) to Rational(0), + mapOf(x to 1u, y to 5u) to Rational(0), + mapOf(x to 2u, y to 5u) to Rational(0), + mapOf(x to 3u, y to 5u) to Rational(0), + mapOf(x to 4u, y to 5u) to Rational(0), + mapOf(y to 6u) to Rational(0), + mapOf(x to 1u, y to 6u) to Rational(0), + mapOf(x to 2u, y to 6u) to Rational(0), + mapOf(x to 3u, y to 6u) to Rational(0), + mapOf(x to 4u, y to 6u) to Rational(0), + ), + LabeledPolynomialAsIs( + mapOf() to Rational(-6, 8), + mapOf(x to 1u) to Rational(-2, 3), + mapOf(x to 2u) to Rational(1, 2), + mapOf(x to 3u) to Rational(0), + mapOf(x to 4u) to Rational(0), + mapOf(y to 1u) to Rational(-18, 3), + mapOf(x to 1u, y to 1u) to Rational(2, 3), + mapOf(x to 2u, y to 1u) to Rational(-11, 1), + mapOf(x to 3u, y to 1u) to Rational(0), + mapOf(x to 4u, y to 1u) to Rational(0), + mapOf(y to 2u) to Rational(-10, 3), + mapOf(x to 1u, y to 2u) to Rational(-8, 5), + mapOf(x to 2u, y to 2u) to Rational(-1, 8), + mapOf(x to 3u, y to 2u) to Rational(0), + mapOf(x to 4u, y to 2u) to Rational(0), + mapOf(y to 3u) to Rational(0), + mapOf(x to 1u, y to 3u) to Rational(0), + mapOf(x to 2u, y to 3u) to Rational(0), + mapOf(x to 3u, y to 3u) to Rational(0), + mapOf(x to 4u, y to 3u) to Rational(0), + mapOf(y to 4u) to Rational(0), + mapOf(x to 1u, y to 4u) to Rational(0), + mapOf(x to 2u, y to 4u) to Rational(0), + mapOf(x to 3u, y to 4u) to Rational(0), + mapOf(x to 4u, y to 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(y to 2u)), + "test 14c" + ) + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt new file mode 100644 index 000000000..5f7e1a95b --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -0,0 +1,544 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.testUtils.IntModuloRing +import space.kscience.kmath.functions.testUtils.ListPolynomial +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import kotlin.test.* + + +class ListPolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2, + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(-2)) + 2, + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + polynomial_4 + 0, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertSame( + polynomial_5, + polynomial_5 + 0, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-1)), + ListPolynomial(Rational(-2)) + 1, + "test 7" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial() + 2, + "test 8" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2, + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(2)) - 2, + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + polynomial_4 - 0, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertEquals( + polynomial_5, + polynomial_5 - 0, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(2)) - 1, + "test 7" + ) + assertEquals( + ListPolynomial(Rational(-2)), + ListPolynomial() - 2, + "test 8" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * 27, + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(7, 0, 49, 21, 14) * 15, + "test 2" + ) + val polynomial = ListPolynomial(22, 26, 13, 15, 26) + assertSame( + zero, + polynomial * 0, + "test 3" + ) + assertSame( + polynomial, + polynomial * 1, + "test 4" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + -3 + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + 2 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + 2 + ListPolynomial(Rational(-2)), + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + 0 + polynomial_4, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertSame( + polynomial_5, + 0 + polynomial_5, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + 1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-1)), + 1 + ListPolynomial(Rational(-2)), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(2)), + 2 + ListPolynomial(), + "test 8" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + 3 - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + -2 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + -2 - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(-32, 9), Rational(-8, -9), Rational(8, 7)), + 0 - ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + "test 4" + ) + assertEquals( + ListPolynomial(), + 0 - ListPolynomial(), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(1)), + -1 - ListPolynomial(Rational(-2)), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(-2)), + -2 - ListPolynomial(), + "test 8" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + val polynomial = ListPolynomial(22, 26, 13, 15, 26) + assertSame( + zero, + 0 * polynomial, + "test 3" + ) + assertSame( + polynomial, + 1 * polynomial, + "test 4" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial() + Rational(0), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + ListPolynomial(Rational(-2)) + Rational(1), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial() + Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial() - Rational(0), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(2)) - Rational(1), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + ListPolynomial() - Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(7, 0, 49, 21, 14) * 15.asConstant(), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(-3) + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(2) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(2) + ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(0) + ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Rational(1) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + Rational(1) + ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + Rational(2) + ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(3) - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(-2) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(-2) - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(0) - ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Rational(-1) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + Rational(-1) - ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + Rational(-2) - ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), + -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.listPolynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 + assertEquals( + ListPolynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + + ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 + assertEquals( + ListPolynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), + ListPolynomial(Rational(-2, 9), Rational(-8, 3)) + + ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 + assertEquals( + ListPolynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)), + ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + + ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + + ListPolynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.listPolynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 + assertEquals( + ListPolynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - + ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 + assertEquals( + ListPolynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), + ListPolynomial(Rational(-2, 9), Rational(-8, 3)) - + ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 + assertEquals( + ListPolynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)), + ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - + ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 + assertEquals( + ListPolynomial(1, 0, 1, 0, 1), + ListPolynomial(1, -1, 1) * ListPolynomial(1, 1, 1), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(5, -25, 10) * ListPolynomial(21, 14, -7), + "test 2" + ) + } + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt new file mode 100644 index 000000000..48ea89a46 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -0,0 +1,982 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.functions.testUtils.assertFailsWithTypeAndMessage +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + + +@OptIn(UnstableKMathAPI::class) +class ListPolynomialUtilTest { + @Test + fun test_Polynomial_substitute_Double() { + assertEquals( + 0.0, + ListPolynomial(1.0, -2.0, 1.0).substitute(1.0), + 0.001, + "test 1" + ) + assertEquals( + 0.0, + ListPolynomial(1.0, -2.0, 1.0).substitute(1.0), + 0.001, + "test 1" + ) + assertEquals( + 1.1931904761904761, + ListPolynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + 0.001, + "test 2" + ) + assertEquals( + 0.5681904761904762, + ListPolynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + 0.001, + "test 3" + ) + assertEquals( + 1.1811904761904761, + ListPolynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).substitute(0.2), + 0.001, + "test 4" + ) + assertEquals( + 1.1703333333333332, + ListPolynomial(0.625, 2.6666666666666665, 0.0, 1.5).substitute(0.2), + 0.001, + "test 5" + ) + } + @Test + fun test_Polynomial_substitute_Constant() { + assertEquals( + Rational(0), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), + "test 1" + ) + assertEquals( + Rational(25057, 21000), + ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 2" + ) + assertEquals( + Rational(2983, 5250), + ListPolynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 3" + ) + assertEquals( + Rational(4961, 4200), + ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0)) + .substitute(RationalField, Rational(1, 5)), + "test 4" + ) + assertEquals( + Rational(3511, 3000), + ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 5" + ) + } + @Test + fun test_Polynomial_substitute_Polynomial() { + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, ListPolynomial(Rational(1))), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(709, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), + ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(2, 7)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(655, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), + ListPolynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(2, 7)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(677, 378), Rational(97, 180), Rational(1, 75), Rational(0)), + ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(0)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(653, 378), Rational(221, 420), Rational(4, 175), Rational(2, 875)), + ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(0), Rational(2, 7)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(89, 54), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(0)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(0))), + "test 6" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_Polynomial_substitute_RationalFunction() { + assertEquals( + ListRationalFunction(ListPolynomial(Rational(0)), ListPolynomial(Rational(1))), + ListPolynomial(Rational(1), Rational(-2), Rational(1)) + .substitute(RationalField, ListRationalFunction(ListPolynomial(Rational(1)), ListPolynomial(Rational(1)))), + "test 1" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(66349, 243), + Rational(-17873, 405), + Rational(173533, 3780), + Rational(-91141, 567), + Rational(5773909, 105840), + Rational(-23243, 630), + Rational(1573, 27) + ), + ListPolynomial( + Rational(169, 81), + Rational(-130, 27), + Rational(115, 18), + Rational(-797, 54), + Rational(1985, 144), + Rational(-55, 6), + Rational(121, 9) + ) + ), + ListPolynomial( + Rational(13, 3), + Rational(-9, 5), + Rational(5, 5) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(15, 1), + Rational(6, 9), + Rational(-3, 7) + ), + ListPolynomial( + Rational(-13, 9), + Rational(10, 6), + Rational(-10, 8), + Rational(11, 3) + ) + ) + ), + "test 2" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(0, 1), + Rational(0, 1), + Rational(-14, 9), + Rational(31, 14), + Rational(-5077, 980), + Rational(99, 35) + ), + ListPolynomial( + Rational(0, 1), + Rational(0, 1), + Rational(25, 9), + Rational(-25, 6), + Rational(1985, 144), + Rational(-55, 6), + Rational(121, 9) + ) + ), + ListPolynomial( + Rational(0), + Rational(-9, 5), + Rational(5, 5) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(0), + Rational(6, 9), + Rational(-3, 7) + ), + ListPolynomial( + Rational(0), + Rational(10, 6), + Rational(-10, 8), + Rational(11, 3) + ) + ) + ), + "test 3" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(-898, 27), + Rational(271, 45), + Rational(-65, 12) , + Rational(0), + Rational(0), + Rational(0), + Rational(0) + ), + ListPolynomial( + Rational(-13, 9), + Rational(5, 3), + Rational(-5, 4), + Rational(0), + Rational(0), + Rational(0), + Rational(0) + ) + ), + ListPolynomial( + Rational(13, 3), + Rational(-9, 5), + Rational(0) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(15, 1), + Rational(6, 9), + Rational(0) + ), + ListPolynomial( + Rational(-13, 9), + Rational(10, 6), + Rational(-10, 8), + Rational(0) + ) + ) + ), + "test 4" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(56872, 243), + Rational(0, 1), + Rational(-90, 7), + Rational(-3718, 81), + Rational(9, 49), + Rational(0, 1), + Rational(1573, 27) + ), + ListPolynomial( + Rational(169, 81), + Rational(0, 1), + Rational(0, 1), + Rational(-286, 27), + Rational(0, 1), + Rational(0, 1), + Rational(121, 9) + ) + ), + ListPolynomial( + Rational(13, 3), + Rational(0), + Rational(5, 5) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(15, 1), + Rational(0), + Rational(-3, 7) + ), + ListPolynomial( + Rational(-13, 9), + Rational(0), + Rational(0), + Rational(11, 3) + ) + ) + ), + "test 5" + ) + } + @Test + fun test_RationalFunction_substitute_Double() { + assertEquals( + 0.0, + ListRationalFunction( + ListPolynomial(1.0, -2.0, 1.0), + ListPolynomial(-6.302012278484357, 5.831971885376948, -9.271604788393432, 5.494387848015814, -3.7187384450880785) + ).substitute(1.0), + 0.001, + "test 1" + ) + assertEquals( + 2.693702616649797, + ListRationalFunction( + ListPolynomial(-5.848840571263625, -1.660411278951134, -3.793740946372443, -9.624569269490076), + ListPolynomial(-2.9680680215311073, -1.862973627119981, 4.776550592888336, -2.7320154512368466) + ).substitute(-7.53452770353279), + 0.001, + "test 2" + ) + assertEquals( + 2.692226268901378, + ListRationalFunction( + ListPolynomial(0.0, -1.660411278951134, -3.793740946372443, -9.624569269490076), + ListPolynomial(0.0, -1.862973627119981, 4.776550592888336, -2.7320154512368466) + ).substitute(-7.53452770353279), + 0.001, + "test 3" + ) + assertEquals( + -0.7394904842099175, + ListRationalFunction( + ListPolynomial(-5.848840571263625, -1.660411278951134, -3.793740946372443, 0.0), + ListPolynomial(-2.9680680215311073, -1.862973627119981, 4.776550592888336, 0.0) + ).substitute(-7.53452770353279), + 0.001, + "test 4" + ) + assertEquals( + 3.526835209398159, + ListRationalFunction( + ListPolynomial(-5.848840571263625, 0.0, 0.0, -9.624569269490076), + ListPolynomial(-2.9680680215311073, 0.0, 0.0, -2.7320154512368466) + ).substitute(-7.53452770353279), + 0.001, + "test 5" + ) + } + @Test + fun test_RationalFunction_substitute_Constant() { + assertEquals( + Rational(0), + ListRationalFunction( + ListPolynomial(Rational(1), Rational(-2), Rational(1)), + ListPolynomial(Rational(1)), + ).substitute(RationalField, Rational(1)), + "test 1" + ) + assertEquals( + Rational(1149615, 61306), + ListRationalFunction( + ListPolynomial(Rational(17, 7), Rational(18, 3), Rational(18, 8), Rational(9, 1)), + ListPolynomial(Rational(11, 9), Rational(-6, 5), Rational(-12, 7), Rational(2, 1)), + ).substitute(RationalField, Rational(-7, 8)), + "test 2" + ) + assertEquals( + Rational(3495, 586), + ListRationalFunction( + ListPolynomial(Rational(0), Rational(18, 3), Rational(18, 8), Rational(9, 1)), + ListPolynomial(Rational(0), Rational(-6, 5), Rational(-12, 7), Rational(2, 1)), + ).substitute(RationalField, Rational(-7, 8)), + "test 3" + ) + assertEquals( + Rational(-88605, 77392), + ListRationalFunction( + ListPolynomial(Rational(17, 7), Rational(18, 3), Rational(18, 8), Rational(0)), + ListPolynomial(Rational(11, 9), Rational(-6, 5), Rational(-12, 7), Rational(0)), + ).substitute(RationalField, Rational(-7, 8)), + "test 4" + ) + assertEquals( + Rational(116145, 3794), + ListRationalFunction( + ListPolynomial(Rational(17, 7), Rational(0), Rational(0), Rational(9, 1)), + ListPolynomial(Rational(11, 9), Rational(0), Rational(0), Rational(2, 1)), + ).substitute(RationalField, Rational(-7, 8)), + "test 5" + ) + } + @Test + fun test_RationalFunction_substitute_Polynomial() { + assertEquals( + ListRationalFunction( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(1)) + ), + ListRationalFunction( + ListPolynomial(Rational(1), Rational(-2), Rational(1)), + ListPolynomial(Rational(1)), + ).substitute(RationalField, ListPolynomial(Rational(1))), + "test 1" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(-283303, 36), + Rational(-23593, 24), + Rational(368713, 192), + Rational(1455, 8), + Rational(-272171, 1536), + Rational(-2149, 192), + Rational(469, 64), + Rational(11, 48), + Rational(-11, 96) + ), + ListPolynomial( + Rational(5797, 12), + Rational(595, 16), + Rational(-5285, 72), + Rational(-745, 192), + Rational(1105, 288), + Rational(5, 48), + Rational(-5, 72) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(2, 9), + Rational(11, 3), + Rational(-9, 4), + Rational(-6, 1), + Rational(-11, 6) + ), + ListPolynomial( + Rational(-2, 3), + Rational(-15, 4), + Rational(5, 9), + Rational(-5, 9) + ) + ).substitute(RationalField, + ListPolynomial( + Rational(-9, 1), + Rational(-1, 4), + Rational(2, 4) + ) + ), + "test 2" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(0, 1), + Rational(-11, 12), + Rational(325, 192), + Rational(21, 32), + Rational(-1739, 1536), + Rational(227, 192), + Rational(-59, 64), + Rational(11, 48), + Rational(-11, 96) + ), + ListPolynomial( + Rational(0, 1), + Rational(15, 16), + Rational(-265, 144), + Rational(-25, 192), + Rational(25, 288), + Rational(5, 48), + Rational(-5, 72) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(0, 9), + Rational(11, 3), + Rational(-9, 4), + Rational(-6, 1), + Rational(-11, 6) + ), + ListPolynomial( + Rational(0, 3), + Rational(-15, 4), + Rational(5, 9), + Rational(-5, 9) + ) + ).substitute(RationalField, + ListPolynomial( + Rational(0, 1), + Rational(-1, 4), + Rational(2, 4) + ) + ), + "test 3" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(149723, 36), + Rational(8483, 24), + Rational(639, 64), + Rational(3, 32), + Rational(0), + Rational(0), + Rational(0), + Rational(0), + Rational(0) + ), + ListPolynomial( + Rational(937, 12), + Rational(55, 16), + Rational(5, 144), + Rational(0), + Rational(0), + Rational(0), + Rational(0) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(2, 9), + Rational(11, 3), + Rational(-9, 4), + Rational(-6, 1), + Rational(0) + ), + ListPolynomial( + Rational(-2, 3), + Rational(-15, 4), + Rational(5, 9), + Rational(0) + ) + ).substitute(RationalField, + ListPolynomial( + Rational(-9, 1), + Rational(-1, 4), + Rational(0) + ) + ), + "test 4" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(-216509, 18), + Rational(0, 1), + Rational(2673, 1), + Rational(0, 1), + Rational(-891, 4), + Rational(0, 1), + Rational(33, 4), + Rational(0, 1), + Rational(-11, 96) + ), + ListPolynomial( + Rational(1213, 3), + Rational(0, 1), + Rational(-135, 2), + Rational(0, 1), + Rational(15, 4), + Rational(0, 1), + Rational(-5, 72) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(2, 9), + Rational(0), + Rational(0), + Rational(0), + Rational(-11, 6) + ), + ListPolynomial( + Rational(-2, 3), + Rational(0), + Rational(0), + Rational(-5, 9) + ) + ).substitute(RationalField, + ListPolynomial( + Rational(-9, 1), + Rational(0), + Rational(2, 4) + ) + ), + "test 5" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction() { + assertEquals( + ListRationalFunction( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(1)) + ), + ListRationalFunction( + ListPolynomial(Rational(1), Rational(-2), Rational(1)), + ListPolynomial(Rational(1)) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(1)) + ) + ), + "test 1" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(130087, 3888), + Rational(-2866333, 65610), + Rational(-5076229, 97200), + Rational(222136997, 3280500), + Rational(754719329, 20995200), + Rational(-12010283, 324000), + Rational(-2011967, 172800), + Rational(18607, 2880), + Rational(4705, 4096) + ), + ListPolynomial( + Rational(-143820355, 3779136), + Rational(73886869, 1574640), + Rational(1440175193, 15746400), + Rational(-5308968857, 52488000), + Rational(-186910083731, 2099520000), + Rational(125043463, 1555200), + Rational(5299123, 388800), + Rational(-213757, 15360), + Rational(1380785, 147456) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(1, 1), + Rational(-10, 5), + Rational(18, 8), + Rational(-8, 8) + ), + ListPolynomial( + Rational(-14, 8), + Rational(-14, 8), + Rational(-19, 6), + Rational(14, 3), + Rational(8, 9) + ) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(14, 9), + Rational(-2, 5), + Rational(-14, 7) + ), + ListPolynomial( + Rational(-6, 4), + Rational(5, 9), + Rational(1, 8) + ) + ) + ), + "test 2" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(5173, 18225), + Rational(904291, 364500), + Rational(283127, 43200), + Rational(37189, 5760), + Rational(147, 128) + ), + ListPolynomial( + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(-163589, 911250), + Rational(-881831, 291600), + Rational(-10722229, 777600), + Rational(-640921, 46080), + Rational(86303, 9216) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(0), + Rational(-10, 5), + Rational(18, 8), + Rational(-8, 8) + ), + ListPolynomial( + Rational(0), + Rational(-14, 8), + Rational(-19, 6), + Rational(14, 3), + Rational(8, 9) + ) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(0), + Rational(-2, 5), + Rational(-14, 7) + ), + ListPolynomial( + Rational(0), + Rational(5, 9), + Rational(1, 8) + ) + ) + ), + "test 3" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(445, 16), + Rational(-2011, 54), + Rational(1359199, 72900), + Rational(-135733, 32805), + Rational(2254, 6561), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1) + ), + ListPolynomial( + Rational(-2018387, 46656), + Rational(82316437, 1574640), + Rational(-9335047, 393660), + Rational(15765889, 3280500), + Rational(-242089, 656100), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1), + Rational(0, 1) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(1, 1), + Rational(-10, 5), + Rational(18, 8), + Rational(0) + ), + ListPolynomial( + Rational(-14, 8), + Rational(-14, 8), + Rational(-19, 6), + Rational(14, 3), + Rational(0) + ) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(14, 9), + Rational(-2, 5), + Rational(0) + ), + ListPolynomial( + Rational(-6, 4), + Rational(5, 9), + Rational(0) + ) + ) + ), + "test 4" + ) + assertEquals( + ListRationalFunction( + ListPolynomial( + Rational(41635, 3888), + Rational(0, 1), + Rational(-279187, 11664), + Rational(0, 1), + Rational(103769, 3456), + Rational(0, 1), + Rational(-11017, 768), + Rational(0, 1), + Rational(4097, 4096) + ), + ListPolynomial( + Rational(-13811791, 3779136), + Rational(0, 1), + Rational(-9999395, 419904), + Rational(0, 1), + Rational(6376601, 124416), + Rational(0, 1), + Rational(-3668315, 82944), + Rational(0, 1), + Rational(2097089, 147456) + ) + ), + ListRationalFunction( + ListPolynomial( + Rational(1, 1), + Rational(0), + Rational(0), + Rational(-8, 8) + ), + ListPolynomial( + Rational(-14, 8), + Rational(0), + Rational(0), + Rational(0), + Rational(8, 9) + ) + ).substitute(RationalField, + ListRationalFunction( + ListPolynomial( + Rational(14, 9), + Rational(0), + Rational(-14, 7) + ), + ListPolynomial( + Rational(-6, 4), + Rational(0), + Rational(1, 8) + ) + ) + ), + "test 5" + ) + } + @Test + fun test_Polynomial_derivative() { + assertEquals( + ListPolynomial(Rational(-2), Rational(2)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), + "test 4" + ) + } + @Test + fun test_Polynomial_nthDerivative() { + assertEquals( + ListPolynomial(Rational(-2), Rational(2)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), + "test 1" + ) + assertFailsWithTypeAndMessage( + "Order of derivative must be non-negative", + "test2" + ) { + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, -1) + } + assertEquals( + ListPolynomial(Rational(1), Rational(-2), Rational(1)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 0), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 2), + "test 4" + ) + assertEquals( + ListPolynomial(), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 3), + "test 5" + ) + assertEquals( + ListPolynomial(), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 4), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), + ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), + "test 8" + ) + assertEquals( + ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(0)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthDerivative(RationalField, 2), + "test 9" + ) + } + @Test + fun test_Polynomial_antiderivative() { + assertEquals( + ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), + "test 4" + ) + } + @Test + fun test_Polynomial_nthAntiderivative() { + assertEquals( + ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), + "test 1" + ) + assertFailsWithTypeAndMessage( + "Order of antiderivative must be non-negative", + "test2" + ) { + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, -1) + } + assertEquals( + ListPolynomial(Rational(1), Rational(-2), Rational(1)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 0), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(1, 2), Rational(-1, 3), Rational(1, 12)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 2), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(1, 6), Rational(-1, 12), Rational(1, 60)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 3), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 24), Rational(-1, 60), Rational(1, 360)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 4), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), + ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), + "test 8" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(0)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthAntiderivative(RationalField, 2), + "test 9" + ) + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt new file mode 100644 index 000000000..ad6240fb9 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + + +class NumberedConstructorsTest { + @Test + @UnstableKMathAPI + fun testDSL1() { + assertEquals( + NumberedPolynomialAsIs( + listOf(2u, 0u, 3u) to 5, + listOf(0u, 1u) to -6, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomialDSL1 { + 5 { 0 pow 2u; 2 pow 3u } + (-6) { 1 pow 1u } + } + }, + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomialDSL1 { + 5 { } + (-6) { } + } + }, + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomialDSL1 { + 5 { 0 pow 1u; 0 pow 1u } + (-6) { 0 pow 2u } + } + }, + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomialDSL1 { + 5 { 0 pow 1u; 0 pow 1u } + (-6) { 0 pow 2u; 2 pow 0u } + } + }, + "test 3" + ) + } + @Test + @UnstableKMathAPI + fun testFabric() { + assertEquals( + NumberedPolynomialAsIs( + listOf(2u, 0u, 3u) to 5, + listOf(0u, 1u) to -6, + ), + Int.algebra { + NumberedPolynomial( + listOf(2u, 0u, 3u) to 5, + listOf(0u, 1u) to -6, + ) + }, + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u, 0u, 3u) to 5, + listOf(0u, 1u) to -6, + ), + Int.algebra { + NumberedPolynomial( + listOf(2u, 0u, 3u, 0u) to 5, + listOf(0u, 1u, 0u, 0u) to -6, + ) + }, + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to -1, + ), + Int.algebra { + NumberedPolynomial( + listOf(0u) to 5, + listOf(0u, 0u) to -6, + ) + }, + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0, + ), + Int.algebra { + NumberedPolynomial( + listOf(0u) to 5, + listOf(0u, 0u) to -5, + ) + }, + "test 4" + ) + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt new file mode 100644 index 000000000..c2f86198c --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -0,0 +1,1740 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.testUtils.IntModuloRing +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.functions.testUtils.m +import space.kscience.kmath.functions.testUtils.o +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertSame +import kotlin.test.fail + + +class NumberedPolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + -3, + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + -3, + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + -3, + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ) + -3, + "test 4" + ) + val polynomial_5 = NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + polynomial_5 + 0, + "test 5" + ) + val polynomial_6 = NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + polynomial_6 + 0, + "test 6" + ) + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + polynomial_7 + 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - 3, + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - 3, + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - 3, + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ) - 3, + "test 4" + ) + val polynomial_5 = NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + polynomial_5 - 0, + "test 5" + ) + val polynomial_6 = NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + polynomial_6 - 0, + "test 6" + ) + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + polynomial_7 - 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to m(34), + listOf(3u) to m(2), + listOf(0u, 1u) to m(1), + listOf(1u) to m(20), + listOf(0u, 0u, 2u) to m(2), + ), + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) * 27, + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + NumberedPolynomial( + listOf() to m(7), + listOf(3u) to m(0), + listOf(0u, 1u) to m(49), + listOf(1u) to m(21), + listOf(0u, 0u, 2u) to m(14), + ) * 15, + "test 2" + ) + val polynomial = NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) + assertSame( + zero, + polynomial * 0, + "test 3" + ) + assertSame( + polynomial, + polynomial * 1, + "test 4" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + -3 + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + -3 + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + -3 + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + -3 + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + "test 4" + ) + val polynomial_5 = NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_5, + 0 + polynomial_5, + "test 5" + ) + val polynomial_6 = NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_6, + 0 + polynomial_6, + "test 6" + ) + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + assertSame( + polynomial_7, + 0 + polynomial_7, + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(22, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 3 - NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(3, 1), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 3 - NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 3 - NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + 3 - NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(22, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 0 - NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 0 - NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + NumberedPolynomial( + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + 0 - NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to m(34), + listOf(3u) to m(2), + listOf(0u, 1u) to m(1), + listOf(1u) to m(20), + listOf(0u, 0u, 2u) to m(2), + ), + 27 * NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + 15 * NumberedPolynomial( + listOf() to m(7), + listOf(3u) to m(0), + listOf(0u, 1u) to m(49), + listOf(1u) to m(21), + listOf(0u, 0u, 2u) to m(14), + ), + "test 2" + ) + val polynomial = NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) + assertSame( + zero, + 0 * polynomial, + "test 3" + ) + assertSame( + polynomial, + 1 * polynomial, + "test 4" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(-3), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ) + Rational(-3), + "test 4" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(0), + "test 5" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(0), + "test 6" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) + Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(3), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(3), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(3), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ) - Rational(3), + "test 4" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(0), + "test 5" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(0), + "test 6" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) - Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to m(34), + listOf(3u) to m(2), + listOf(0u, 1u) to m(1), + listOf(1u) to m(20), + listOf(0u, 0u, 2u) to m(2), + ), + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) * m(27), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + NumberedPolynomial( + listOf() to m(7), + listOf(3u) to m(0), + listOf(0u, 1u) to m(49), + listOf(1u) to m(21), + listOf(0u, 0u, 2u) to m(14), + ) * m(15), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) * m(0), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ) * m(1), + "test 4" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(-3) + NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-3, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(-3) + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(-3) + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + Rational(-3) + NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(0) + NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(0) + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + Rational(0) + NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(22, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(3) - NumberedPolynomial( + listOf() to Rational(5, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(3, 1), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(3) - NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 1), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(3) - NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + Rational(3) - NumberedPolynomial( + listOf() to Rational(27, 9), + listOf(3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + ), + "test 4" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(22, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(0) - NumberedPolynomial( + listOf() to Rational(-22, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 5" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(0) - NumberedPolynomial( + listOf() to Rational(0, 9), + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 6" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(3u) to Rational(8, 9), + listOf(0u, 4u) to Rational(8, 7), + ), + Rational(0) - NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to m(34), + listOf(3u) to m(2), + listOf(0u, 1u) to m(1), + listOf(1u) to m(20), + listOf(0u, 0u, 2u) to m(2), + ), + m(27) * NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + m(15) * NumberedPolynomial( + listOf() to m(7), + listOf(3u) to m(0), + listOf(0u, 1u) to m(49), + listOf(1u) to m(21), + listOf(0u, 0u, 2u) to m(14), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(0), + listOf(3u) to m(0), + listOf(0u, 1u) to m(0), + listOf(1u) to m(0), + listOf(0u, 0u, 2u) to m(0), + ), + m(0) * NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + m(1) * NumberedPolynomial( + listOf() to m(22), + listOf(3u) to m(26), + listOf(0u, 1u) to m(13), + listOf(1u) to m(15), + listOf(0u, 0u, 2u) to m(26), + ), + "test 4" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf(5u) to Rational(-5, 9), + listOf() to Rational(8, 9), + listOf(0u, 0u, 0u, 0u, 0u, 0u, 13u) to Rational(8, 7), + ), + -NumberedPolynomial( + listOf(5u) to Rational(5, 9), + listOf() to Rational(-8, 9), + listOf(0u, 0u, 0u, 0u, 0u, 0u, 13u) to Rational(-8, 7), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf(5u) to Rational(-5, 9), + listOf() to Rational(8, 9), + listOf(0u, 0u, 0u, 0u, 0u, 0u, 13u) to Rational(8, 7), + listOf(0u, 4u) to Rational(0), + listOf(5u) to Rational(0), + ), + -NumberedPolynomial( + listOf(5u) to Rational(5, 9), + listOf() to Rational(-8, 9), + listOf(0u, 0u, 0u, 0u, 0u, 0u, 13u) to Rational(-8, 7), + listOf(0u, 4u) to Rational(0), + listOf(5u) to Rational(0), + ), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(146, 63), + listOf(1u, 1u) to Rational(-3, 5), + listOf(2u, 1u) to Rational(61, 15), + listOf(0u, 2u) to Rational(157, 63), + listOf(1u, 2u) to Rational(-55, 21), + listOf(2u, 2u) to Rational(11, 24), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(-7, 7), + listOf(2u, 1u) to Rational(12, 5), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) + NumberedPolynomial( + listOf() to Rational(-20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(-20, 7), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(7, 9), + listOf(1u, 2u) to Rational(5, 7), + listOf(2u, 2u) to Rational(-2, 3), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(157, 63), + listOf(1u, 2u) to Rational(-55, 21), + listOf(2u, 2u) to Rational(11, 24), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) + NumberedPolynomial( + listOf() to Rational(-20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(-20, 7), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(7, 9), + listOf(1u, 2u) to Rational(5, 7), + listOf(2u, 2u) to Rational(-2, 3), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) + NumberedPolynomial( + listOf() to Rational(-20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(-20, 7), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(-7, 7), + listOf(2u, 1u) to Rational(12, 5), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) + NumberedPolynomial( + listOf() to Rational(-6, 4), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(-10, 6), + listOf(0u, 1u) to Rational(-17, 7), + listOf(1u, 1u) to Rational(7, 7), + listOf(2u, 1u) to Rational(-12, 5), + listOf(0u, 2u) to Rational(-12, 7), + listOf(1u, 2u) to Rational(10, 3), + listOf(2u, 2u) to Rational(-9, 8), + ), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(146, 63), + listOf(1u, 1u) to Rational(-3, 5), + listOf(2u, 1u) to Rational(61, 15), + listOf(0u, 2u) to Rational(157, 63), + listOf(1u, 2u) to Rational(-55, 21), + listOf(2u, 2u) to Rational(11, 24), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(-7, 7), + listOf(2u, 1u) to Rational(12, 5), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) - NumberedPolynomial( + listOf() to Rational(20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(20, 7), + listOf(0u, 1u) to Rational(1, 9), + listOf(1u, 1u) to Rational(-2, 5), + listOf(2u, 1u) to Rational(-10, 6), + listOf(0u, 2u) to Rational(-7, 9), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(2, 3), + ), + "test 1" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(157, 63), + listOf(1u, 2u) to Rational(-55, 21), + listOf(2u, 2u) to Rational(11, 24), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) - NumberedPolynomial( + listOf() to Rational(20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(20, 7), + listOf(0u, 1u) to Rational(1, 9), + listOf(1u, 1u) to Rational(-2, 5), + listOf(2u, 1u) to Rational(-10, 6), + listOf(0u, 2u) to Rational(-7, 9), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(2, 3), + ), + "test 2" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(-17, 2), + listOf(1u) to Rational(-1, 3), + listOf(2u) to Rational(-25, 21), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(2, 5), + listOf(2u, 1u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) - NumberedPolynomial( + listOf() to Rational(20, 2), + listOf(1u) to Rational(0, 9), + listOf(2u) to Rational(20, 7), + listOf(0u, 1u) to Rational(1, 9), + listOf(1u, 1u) to Rational(-2, 5), + listOf(2u, 1u) to Rational(-10, 6), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + ), + "test 3" + ) + assertEquals( + NumberedPolynomial( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + ), + NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(-7, 7), + listOf(2u, 1u) to Rational(12, 5), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ) - NumberedPolynomial( + listOf() to Rational(6, 4), + listOf(1u) to Rational(-2, 6), + listOf(2u) to Rational(10, 6), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(-7, 7), + listOf(2u, 1u) to Rational(12, 5), + listOf(0u, 2u) to Rational(12, 7), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(9, 8), + ), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).numberedPolynomialSpace { + // (p + q + r) * (p^2 + q^2 + r^2 - pq - pr - qr) = p^3 + q^3 + r^3 - 3pqr + assertEquals( + NumberedPolynomial( + listOf(3u) to m(1), + listOf(0u, 3u) to m(1), + listOf(0u, 0u, 3u) to m(1), + listOf(1u, 2u) to m(0), + listOf(0u, 1u, 2u) to m(0), + listOf(2u, 0u, 1u) to m(0), + listOf(1u, 0u, 2u) to m(0), + listOf(2u, 1u) to m(0), + listOf(0u, 2u, 1u) to m(0), + listOf(1u, 1u, 1u) to m(-3), + ), + NumberedPolynomial( + listOf(1u) to m(1), + listOf(0u, 1u) to m(1), + listOf(0u, 0u, 1u) to m(1), + ) * NumberedPolynomial( + listOf(2u) to m(1), + listOf(0u, 2u) to m(1), + listOf(0u, 0u, 2u) to m(1), + listOf(1u, 1u) to m(-1), + listOf(0u, 1u, 1u) to m(-1), + listOf(1u, 0u, 1u) to m(-1), + ), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + NumberedPolynomial( + listOf(2u) to m(0), + listOf(0u, 2u) to m(0), + listOf(0u, 0u, 2u) to m(0), + listOf(1u, 1u) to m(0), + listOf(0u, 1u, 1u) to m(0), + listOf(1u, 0u, 1u) to m(0), + ), + NumberedPolynomial( + listOf(1u) to m(5), + listOf(0u, 1u) to m(-25), + listOf(0u, 0u, 1u) to m(10), + ) * NumberedPolynomial( + listOf(1u) to m(21), + listOf(0u, 1u) to m(14), + listOf(0u, 0u, 1u) to m(-7), + ), + "test 2" + ) + } + } + @Test + fun test_lastVariable() { + RationalField.numberedPolynomialSpace { + assertEquals( + -1, + NumberedPolynomial().lastVariable, + "test 1" + ) + assertEquals( + -1, + NumberedPolynomial( + listOf() to o + ).lastVariable, + "test 2" + ) + assertEquals( + 2, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).lastVariable, + "test 3" + ) + assertEquals( + 3, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).also { println(it) }.lastVariable, + "test 4" + ) + assertEquals( + 2, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).lastVariable, + "test 5" + ) + } + } + @Test + fun test_degree() { + RationalField.numberedPolynomialSpace { + assertEquals( + -1, + NumberedPolynomial().degree, + "test 1" + ) + assertEquals( + 0, + NumberedPolynomial( + listOf() to o + ).degree, + "test 2" + ) + assertEquals( + 6, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).degree, + "test 3" + ) + assertEquals( + 4, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).degree, + "test 4" + ) + assertEquals( + 3, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).degree, + "test 5" + ) + assertEquals( + 4, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ).degree, + "test 6" + ) + } + } + @Test + fun test_degrees() { + RationalField.numberedPolynomialSpace { + assertEquals( + listOf(), + NumberedPolynomial().degrees, + "test 1" + ) + assertEquals( + listOf(), + NumberedPolynomial( + listOf() to o + ).degrees, + "test 2" + ) + assertEquals( + listOf(1u, 2u, 3u), + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).degrees, + "test 3" + ) + assertEquals( + listOf(0u, 1u, 2u, 1u), + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).degrees, + "test 4" + ) + assertEquals( + listOf(2u, 1u, 1u), + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).degrees, + "test 5" + ) + assertEquals( + listOf(2u, 2u, 2u, 4u), + NumberedPolynomial( + listOf() to o, + listOf(1u, 2u) to o, + listOf(0u, 1u, 2u) to o, + listOf(2u, 0u, 1u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ).degrees, + "test 6" + ) + } + } + @Test + fun test_degreeBy() { + RationalField.numberedPolynomialSpace { + fun NumberedPolynomial.collectDegrees(limit: Int = lastVariable + 2): List = List(limit) { degreeBy(it) } + assertEquals( + listOf(0u), + NumberedPolynomial().collectDegrees(), + "test 1" + ) + assertEquals( + listOf(0u), + NumberedPolynomial( + listOf() to o + ).collectDegrees(), + "test 2" + ) + assertEquals( + listOf(1u, 2u, 3u, 0u), + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).collectDegrees(), + "test 3" + ) + assertEquals( + listOf(0u, 1u, 2u, 1u, 0u), + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).collectDegrees(), + "test 4" + ) + assertEquals( + listOf(2u, 1u, 1u, 0u), + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).collectDegrees(), + "test 5" + ) + assertEquals( + listOf(2u, 2u, 2u, 4u, 0u), + NumberedPolynomial( + listOf() to o, + listOf(1u, 2u) to o, + listOf(0u, 1u, 2u) to o, + listOf(2u, 0u, 1u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ).collectDegrees(), + "test 6" + ) + } + } + @Test + fun test_degreeBy_Collection() { + RationalField.numberedPolynomialSpace { + fun NumberedPolynomial.checkDegreeBy(message: String? = null) { + val lastVariable = lastVariable + val indexCollectionSequence: Sequence> = sequence { + val appearances = MutableList(lastVariable + 2) { 0 } + while (true) { + yield( + buildList { + for ((variable, count) in appearances.withIndex()) repeat(count) { add(variable) } + } + ) + val indexChange = appearances.indexOfFirst { it < 4 } + if (indexChange == -1) break + appearances[indexChange] += 1 + for (index in 0 until indexChange) appearances[index] = 0 + } + } + for (indexCollection in indexCollectionSequence) { + val expected = coefficients.keys.maxOfOrNull { degs -> degs.slice(indexCollection.distinct().filter { it in degs.indices }).sum() } ?: 0u + val actual = degreeBy(indexCollection) + if (actual != expected) + fail("${message ?: ""} Incorrect answer for variable collection $indexCollection: expected $expected, actual $actual") + } + } + NumberedPolynomial().checkDegreeBy("test 1") + NumberedPolynomial( + listOf() to o + ).checkDegreeBy("test 2") + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).checkDegreeBy("test 3") + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).checkDegreeBy("test 4") + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).checkDegreeBy("test 5") + NumberedPolynomial( + listOf() to o, + listOf(1u, 2u) to o, + listOf(0u, 1u, 2u) to o, + listOf(2u, 0u, 1u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ).checkDegreeBy("test 6") + } + } + @Test + fun test_countOfVariables() { + RationalField.numberedPolynomialSpace { + assertEquals( + 0, + NumberedPolynomial().countOfVariables, + "test 1" + ) + assertEquals( + 0, + NumberedPolynomial( + listOf() to o + ).countOfVariables, + "test 2" + ) + assertEquals( + 3, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).countOfVariables, + "test 3" + ) + assertEquals( + 3, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).countOfVariables, + "test 4" + ) + assertEquals( + 3, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).countOfVariables, + "test 5" + ) + assertEquals( + 4, + NumberedPolynomial( + listOf() to o, + listOf(1u, 2u) to o, + listOf(0u, 1u, 2u) to o, + listOf(2u, 0u, 1u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ).countOfVariables, + "test 6" + ) + } + } + @Test + fun test_RF_countOfVariables() { + RationalField.numberedRationalFunctionSpace { + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial() + ).countOfVariables, + "test 1" + ) + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial(), + NumberedPolynomial() + ).countOfVariables, + "test 2" + ) + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial( + listOf() to o + ) + ).countOfVariables, + "test 3" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ) + ).countOfVariables, + "test 4" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial( + listOf(0u, 1u, 0u, 1u) to o + ), + NumberedPolynomial( + listOf(0u, 0u, 2u) to o + ) + ).countOfVariables, + "test 5" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ) + ).countOfVariables, + "test 6" + ) + assertEquals( + 4, + NumberedRationalFunction( + NumberedPolynomial( + listOf() to o, + listOf(1u, 2u) to o, + listOf(2u, 0u, 1u) to o, + ), NumberedPolynomial( + listOf(0u, 1u, 2u) to o, + listOf(0u, 0u, 0u, 4u) to o, + ) + ).countOfVariables, + "test 7" + ) + } + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt new file mode 100644 index 000000000..e5d1ddf48 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -0,0 +1,12021 @@ +/* + * Copyright 2018-2022 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.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.functions.testUtils.assertFailsWithTypeAndMessage +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals +import space.kscience.kmath.functions.testUtils.bufferOf +import space.kscience.kmath.functions.testUtils.assertEquals + + +class NumberedPolynomialUtilTest { + @Test + fun test_Polynomial_substitute_Double_Map() { + assertEquals( + NumberedPolynomialAsIs(emptyList() to 0.0), + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ).substitute(mapOf( + 0 to 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf()), + 0.001, + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 5 to 0.9211194782050933 + )), + 0.001, + "test 2'" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(0u, 1u) to 0.4561746111587508, + listOf(0u, 2u) to 0.2700930201481795, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 0 to 0.0 + )), + 0.001, + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(0u, 1u) to 0.4561746111587508, + listOf(0u, 2u) to 0.2700930201481795, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 0 to 0.0, + 5 to 0.9211194782050933 + )), + 0.001, + "test 3'" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.433510890645169, + listOf(1u) to 0.6264844682514724, + listOf(2u) to 0.8405727903771333, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 1 to 0.8400458576651112 + )), + 0.001, + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.433510890645169, + listOf(1u) to 0.6264844682514724, + listOf(2u) to 0.8405727903771333, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 1 to 0.8400458576651112, + 5 to 0.9211194782050933 + )), + 0.001, + "test 4'" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.934530767358133, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 0 to 0.4846192734143442, + 1 to 0.8400458576651112, + )), + 0.001, + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.934530767358133, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(mapOf( + 0 to 0.4846192734143442, + 1 to 0.8400458576651112, + 5 to 0.9211194782050933 + )), + 0.001, + "test 5'" + ) + } + @Test + fun test_Polynomial_substitute_Constant_Map() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, mapOf( + 0 to Rational(1) + )), + "test 1" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5%2C+y+%3D+12%2F9 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(143, 150) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to Rational(-2, 5), + 1 to Rational(12, 9), + )), + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(143, 150) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to Rational(-2, 5), + 1 to Rational(12, 9), + 5 to Rational(57, 179), + )), + "test 2'" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+y+%3D+12%2F9 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-67, 18), + listOf(1u) to Rational(-70, 9), + listOf(2u) to Rational(88, 9), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 1 to Rational(12, 9), + )), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-67, 18), + listOf(1u) to Rational(-70, 9), + listOf(2u) to Rational(88, 9), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 1 to Rational(12, 9), + 5 to Rational(57, 179), + )), + "test 3'" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-83, 50), + listOf(0u, 1u) to Rational(29, 25), + listOf(0u, 2u) to Rational(3, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to Rational(-2, 5), + )), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-83, 50), + listOf(0u, 1u) to Rational(29, 25), + listOf(0u, 2u) to Rational(3, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to Rational(-2, 5), + 5 to Rational(57, 179), + )), + "test 4'" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf()), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 5 to Rational(57, 179), + )), + "test 5'" + ) + // https://www.wolframalpha.com/input?i=%28%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2%29+p%5E8+where+x+%3D+q%2Fp%2C+y+%3D+x%5E3%2C+p+%3D+-2%2F5%2C+q+%3D+12%2F9 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(47639065216, 2562890625) + ), + NumberedPolynomialAsIs( + listOf(8u) to Rational(-3, 2), + listOf(7u, 1u) to Rational(8, 6), + listOf(6u, 2u) to Rational(14, 6), + listOf(5u, 3u) to Rational(-3, 1), + listOf(4u, 4u) to Rational(-19, 2), + listOf(3u, 5u) to Rational(9, 4), + listOf(2u, 6u) to Rational(5, 5), + listOf(1u, 7u) to Rational(18, 9), + listOf(0u, 8u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to Rational(-2, 5), + 1 to Rational(12, 9), + )), + "test 6" + ) + } + @Test + fun test_Polynomial_substitute_Polynomial_Map() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + )), + "test 1" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-5%2F1+s+%2B+2%2F8+t%2C+y+%3D+11%2F7+t + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(0u, 1u) to Rational(-92, 21), + listOf(0u, 2u) to Rational(-2627, 2352), + listOf(0u, 3u) to Rational(4565, 3136), + listOf(0u, 4u) to Rational(605, 1568), + listOf(1u) to Rational(-20, 3), + listOf(1u, 1u) to Rational(1445, 21), + listOf(1u, 2u) to Rational(-13145, 392), + listOf(1u, 3u) to Rational(-3025, 196), + listOf(2u) to Rational(175, 3), + listOf(2u, 1u) to Rational(2475, 28), + listOf(2u, 2u) to Rational(15125, 98), + listOf(3u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf(1u) to Rational(-5, 1), + listOf(0u, 1u) to Rational(2, 8), + ), + 1 to NumberedPolynomialAsIs( + listOf(1u) to Rational(0, 5), + listOf(0u, 1u) to Rational(11, 7), + ), + )), + "test 2" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = (-9/2 + 2/7 s + 9/1 s^2) + (13/1 + -1/8 s + 2/8 s^2) t + (19/4 + 15/7 s + -19/4 s^2) t^2 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(48583, 336), + listOf(2u) to Rational(-913477, 1568), + listOf(3u) to Rational(-967567, 672), + listOf(4u) to Rational(4722043, 1344), + listOf(5u) to Rational(8855, 2), + listOf(6u) to Rational(-311971, 32), + listOf(7u) to Rational(-17325, 4), + listOf(8u) to Rational(19845, 2), + listOf(0u, 1u) to Rational(-827, 4), + listOf(1u, 1u) to Rational(191927, 840), + listOf(2u, 1u) to Rational(9592627, 2352), + listOf(3u, 1u) to Rational(-105400711, 53760), + listOf(4u, 1u) to Rational(-10054101459, 439040), + listOf(5u, 1u) to Rational(2127351, 128), + listOf(6u, 1u) to Rational(116680973, 3136), + listOf(7u, 1u) to Rational(-220445, 7), + listOf(8u, 1u) to Rational(-2655, 4), + listOf(0u, 2u) to Rational(30567, 100), + listOf(1u, 2u) to Rational(-156284953, 39200), + listOf(2u, 2u) to Rational(-57661541711, 6585600), + listOf(3u, 2u) to Rational(131931579, 3136), + listOf(4u, 2u) to Rational(98818124791, 3512320), + listOf(5u, 2u) to Rational(-94458855053, 878080), + listOf(6u, 2u) to Rational(13937705305, 1229312), + listOf(7u, 2u) to Rational(335706887, 21952), + listOf(8u, 2u) to Rational(23549165, 1568), + listOf(0u, 3u) to Rational(111367, 1400), + listOf(1u, 3u) to Rational(4937369, 700), + listOf(2u, 3u) to Rational(-4449423711, 274400), + listOf(3u, 3u) to Rational(-351873325703, 4390400), + listOf(4u, 3u) to Rational(23495875029, 307328), + listOf(5u, 3u) to Rational(17576300919, 878080), + listOf(6u, 3u) to Rational(230316993, 12544), + listOf(7u, 3u) to Rational(-191130515, 21952), + listOf(8u, 3u) to Rational(332435, 392), + listOf(0u, 4u) to Rational(-275084, 1225), + listOf(1u, 4u) to Rational(-266774603, 137200), + listOf(2u, 4u) to Rational(2176279167121, 30732800), + listOf(3u, 4u) to Rational(10904913303, 2195200), + listOf(4u, 4u) to Rational(-10769286147, 2195200), + listOf(5u, 4u) to Rational(-26277119793, 439040), + listOf(6u, 4u) to Rational(25859735869, 6146560), + listOf(7u, 4u) to Rational(38906289, 2744), + listOf(8u, 4u) to Rational(-3072025, 392), + listOf(0u, 5u) to Rational(9573, 98), + listOf(1u, 5u) to Rational(-4154651399, 548800), + listOf(2u, 5u) to Rational(3446069019, 548800), + listOf(3u, 5u) to Rational(-7851500623, 137200), + listOf(4u, 5u) to Rational(-53205142903, 1920800), + listOf(5u, 5u) to Rational(-31953611, 3430), + listOf(6u, 5u) to Rational(1447380313, 109760), + listOf(7u, 5u) to Rational(764158625, 21952), + listOf(8u, 5u) to Rational(1153515, 784), + listOf(0u, 6u) to Rational(1722351, 7840), + listOf(1u, 6u) to Rational(-164554821, 109760), + listOf(2u, 6u) to Rational(-79096147243, 7683200), + listOf(3u, 6u) to Rational(-624721089, 15680), + listOf(4u, 6u) to Rational(11147305567, 548800), + listOf(5u, 6u) to Rational(8318333679, 109760), + listOf(6u, 6u) to Rational(32981871553, 1536640), + listOf(7u, 6u) to Rational(-225359619, 21952), + listOf(8u, 6u) to Rational(-3973995, 392), + listOf(0u, 7u) to Rational(67203, 784), + listOf(1u, 7u) to Rational(39281469, 54880), + listOf(2u, 7u) to Rational(70162551, 27440), + listOf(3u, 7u) to Rational(413630709, 54880), + listOf(4u, 7u) to Rational(4640410269, 192080), + listOf(5u, 7u) to Rational(802712247, 54880), + listOf(6u, 7u) to Rational(-473517603, 27440), + listOf(7u, 7u) to Rational(-17055459, 1568), + listOf(8u, 7u) to Rational(-12825, 14), + listOf(0u, 8u) to Rational(16245, 1568), + listOf(1u, 8u) to Rational(503253, 2744), + listOf(2u, 8u) to Rational(125292591, 96040), + listOf(3u, 8u) to Rational(12033171, 2744), + listOf(4u, 8u) to Rational(154352673, 27440), + listOf(5u, 8u) to Rational(-1302291, 392), + listOf(6u, 8u) to Rational(-20265741, 1960), + listOf(7u, 8u) to Rational(-26163, 56), + listOf(8u, 8u) to Rational(146205, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + 1 to NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + )), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(48583, 336), + listOf(2u) to Rational(-913477, 1568), + listOf(3u) to Rational(-967567, 672), + listOf(4u) to Rational(4722043, 1344), + listOf(5u) to Rational(8855, 2), + listOf(6u) to Rational(-311971, 32), + listOf(7u) to Rational(-17325, 4), + listOf(8u) to Rational(19845, 2), + listOf(0u, 1u) to Rational(-827, 4), + listOf(1u, 1u) to Rational(191927, 840), + listOf(2u, 1u) to Rational(9592627, 2352), + listOf(3u, 1u) to Rational(-105400711, 53760), + listOf(4u, 1u) to Rational(-10054101459, 439040), + listOf(5u, 1u) to Rational(2127351, 128), + listOf(6u, 1u) to Rational(116680973, 3136), + listOf(7u, 1u) to Rational(-220445, 7), + listOf(8u, 1u) to Rational(-2655, 4), + listOf(0u, 2u) to Rational(30567, 100), + listOf(1u, 2u) to Rational(-156284953, 39200), + listOf(2u, 2u) to Rational(-57661541711, 6585600), + listOf(3u, 2u) to Rational(131931579, 3136), + listOf(4u, 2u) to Rational(98818124791, 3512320), + listOf(5u, 2u) to Rational(-94458855053, 878080), + listOf(6u, 2u) to Rational(13937705305, 1229312), + listOf(7u, 2u) to Rational(335706887, 21952), + listOf(8u, 2u) to Rational(23549165, 1568), + listOf(0u, 3u) to Rational(111367, 1400), + listOf(1u, 3u) to Rational(4937369, 700), + listOf(2u, 3u) to Rational(-4449423711, 274400), + listOf(3u, 3u) to Rational(-351873325703, 4390400), + listOf(4u, 3u) to Rational(23495875029, 307328), + listOf(5u, 3u) to Rational(17576300919, 878080), + listOf(6u, 3u) to Rational(230316993, 12544), + listOf(7u, 3u) to Rational(-191130515, 21952), + listOf(8u, 3u) to Rational(332435, 392), + listOf(0u, 4u) to Rational(-275084, 1225), + listOf(1u, 4u) to Rational(-266774603, 137200), + listOf(2u, 4u) to Rational(2176279167121, 30732800), + listOf(3u, 4u) to Rational(10904913303, 2195200), + listOf(4u, 4u) to Rational(-10769286147, 2195200), + listOf(5u, 4u) to Rational(-26277119793, 439040), + listOf(6u, 4u) to Rational(25859735869, 6146560), + listOf(7u, 4u) to Rational(38906289, 2744), + listOf(8u, 4u) to Rational(-3072025, 392), + listOf(0u, 5u) to Rational(9573, 98), + listOf(1u, 5u) to Rational(-4154651399, 548800), + listOf(2u, 5u) to Rational(3446069019, 548800), + listOf(3u, 5u) to Rational(-7851500623, 137200), + listOf(4u, 5u) to Rational(-53205142903, 1920800), + listOf(5u, 5u) to Rational(-31953611, 3430), + listOf(6u, 5u) to Rational(1447380313, 109760), + listOf(7u, 5u) to Rational(764158625, 21952), + listOf(8u, 5u) to Rational(1153515, 784), + listOf(0u, 6u) to Rational(1722351, 7840), + listOf(1u, 6u) to Rational(-164554821, 109760), + listOf(2u, 6u) to Rational(-79096147243, 7683200), + listOf(3u, 6u) to Rational(-624721089, 15680), + listOf(4u, 6u) to Rational(11147305567, 548800), + listOf(5u, 6u) to Rational(8318333679, 109760), + listOf(6u, 6u) to Rational(32981871553, 1536640), + listOf(7u, 6u) to Rational(-225359619, 21952), + listOf(8u, 6u) to Rational(-3973995, 392), + listOf(0u, 7u) to Rational(67203, 784), + listOf(1u, 7u) to Rational(39281469, 54880), + listOf(2u, 7u) to Rational(70162551, 27440), + listOf(3u, 7u) to Rational(413630709, 54880), + listOf(4u, 7u) to Rational(4640410269, 192080), + listOf(5u, 7u) to Rational(802712247, 54880), + listOf(6u, 7u) to Rational(-473517603, 27440), + listOf(7u, 7u) to Rational(-17055459, 1568), + listOf(8u, 7u) to Rational(-12825, 14), + listOf(0u, 8u) to Rational(16245, 1568), + listOf(1u, 8u) to Rational(503253, 2744), + listOf(2u, 8u) to Rational(125292591, 96040), + listOf(3u, 8u) to Rational(12033171, 2744), + listOf(4u, 8u) to Rational(154352673, 27440), + listOf(5u, 8u) to Rational(-1302291, 392), + listOf(6u, 8u) to Rational(-20265741, 1960), + listOf(7u, 8u) to Rational(-26163, 56), + listOf(8u, 8u) to Rational(146205, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + 1 to NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-11, 3), + listOf(1u) to Rational(5, 2), + listOf(2u) to Rational(13, 7), + listOf(0u, 1u) to Rational(16, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(6, 1), + listOf(0u, 2u) to Rational(-14, 3), + listOf(1u, 2u) to Rational(-2, 7), + listOf(2u, 2u) to Rational(-10, 8), + ) + )), + "test 3'" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = s, y = (-9/2 + 2/7 s + 9/1 s^2) + (13/1 + -1/8 s + 2/8 s^2) t + (19/4 + 15/7 s + -19/4 s^2) t^2 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(6817, 84), + listOf(2u) to Rational(-21445, 294), + listOf(3u) to Rational(-12151, 49), + listOf(4u) to Rational(-17789, 196), + listOf(5u) to Rational(1224, 7), + listOf(6u) to Rational(405, 2), + listOf(0u, 1u) to Rational(-156), + listOf(1u, 1u) to Rational(-2440, 7), + listOf(2u, 1u) to Rational(-1571, 112), + listOf(3u, 1u) to Rational(107515, 224), + listOf(4u, 1u) to Rational(64965, 112), + listOf(5u, 1u) to Rational(209, 56), + listOf(6u, 1u) to Rational(45, 4), + listOf(0u, 2u) to Rational(112), + listOf(1u, 2u) to Rational(1449, 8), + listOf(2u, 2u) to Rational(1306309, 3136), + listOf(3u, 2u) to Rational(483207, 1568), + listOf(4u, 2u) to Rational(1978437, 6272), + listOf(5u, 2u) to Rational(-18231, 224), + listOf(6u, 2u) to Rational(-6835, 32), + listOf(0u, 3u) to Rational(247, 2), + listOf(1u, 3u) to Rational(33771, 112), + listOf(2u, 3u) to Rational(2073, 7), + listOf(3u, 3u) to Rational(-23463, 224), + listOf(4u, 3u) to Rational(-33825, 112), + listOf(5u, 3u) to Rational(201, 224), + listOf(6u, 3u) to Rational(-95, 16), + listOf(0u, 4u) to Rational(361, 16), + listOf(1u, 4u) to Rational(3667, 56), + listOf(2u, 4u) to Rational(88729, 1568), + listOf(3u, 4u) to Rational(-2476, 49), + listOf(4u, 4u) to Rational(-23419, 196), + listOf(5u, 4u) to Rational(-323, 56), + listOf(6u, 4u) to Rational(1805, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 1 to NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + )), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(6817, 84), + listOf(2u) to Rational(-21445, 294), + listOf(3u) to Rational(-12151, 49), + listOf(4u) to Rational(-17789, 196), + listOf(5u) to Rational(1224, 7), + listOf(6u) to Rational(405, 2), + listOf(0u, 1u) to Rational(-156), + listOf(1u, 1u) to Rational(-2440, 7), + listOf(2u, 1u) to Rational(-1571, 112), + listOf(3u, 1u) to Rational(107515, 224), + listOf(4u, 1u) to Rational(64965, 112), + listOf(5u, 1u) to Rational(209, 56), + listOf(6u, 1u) to Rational(45, 4), + listOf(0u, 2u) to Rational(112), + listOf(1u, 2u) to Rational(1449, 8), + listOf(2u, 2u) to Rational(1306309, 3136), + listOf(3u, 2u) to Rational(483207, 1568), + listOf(4u, 2u) to Rational(1978437, 6272), + listOf(5u, 2u) to Rational(-18231, 224), + listOf(6u, 2u) to Rational(-6835, 32), + listOf(0u, 3u) to Rational(247, 2), + listOf(1u, 3u) to Rational(33771, 112), + listOf(2u, 3u) to Rational(2073, 7), + listOf(3u, 3u) to Rational(-23463, 224), + listOf(4u, 3u) to Rational(-33825, 112), + listOf(5u, 3u) to Rational(201, 224), + listOf(6u, 3u) to Rational(-95, 16), + listOf(0u, 4u) to Rational(361, 16), + listOf(1u, 4u) to Rational(3667, 56), + listOf(2u, 4u) to Rational(88729, 1568), + listOf(3u, 4u) to Rational(-2476, 49), + listOf(4u, 4u) to Rational(-23419, 196), + listOf(5u, 4u) to Rational(-323, 56), + listOf(6u, 4u) to Rational(1805, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 1 to NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-11, 3), + listOf(1u) to Rational(5, 2), + listOf(2u) to Rational(13, 7), + listOf(0u, 1u) to Rational(16, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(6, 1), + listOf(0u, 2u) to Rational(-14, 3), + listOf(1u, 2u) to Rational(-2, 7), + listOf(2u, 2u) to Rational(-10, 8), + ) + )), + "test 4'" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = t + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(7, 3), + listOf(2u) to Rational(-35, 16), + listOf(3u) to Rational(-343, 6), + listOf(4u) to Rational(343, 3), + listOf(0u, 1u) to Rational(-19, 5), + listOf(1u, 1u) to Rational(-823, 120), + listOf(2u, 1u) to Rational(1232417, 6720), + listOf(3u, 1u) to Rational(-9863, 24), + listOf(4u, 1u) to Rational(385, 4), + listOf(0u, 2u) to Rational(2439, 350), + listOf(1u, 2u) to Rational(-5793, 40), + listOf(2u, 2u) to Rational(1172113, 3360), + listOf(3u, 2u) to Rational(-13531, 40), + listOf(4u, 2u) to Rational(2824, 7), + listOf(0u, 3u) to Rational(3417, 700), + listOf(1u, 3u) to Rational(1191, 200), + listOf(2u, 3u) to Rational(8383, 28), + listOf(3u, 3u) to Rational(-220279, 280), + listOf(4u, 3u) to Rational(49179, 196), + listOf(0u, 4u) to Rational(57, 35), + listOf(1u, 4u) to Rational(-33771, 700), + listOf(2u, 4u) to Rational(196279, 1225), + listOf(3u, 4u) to Rational(-32259, 140), + listOf(4u, 4u) to Rational(23868, 49), + listOf(0u, 5u) to Rational(333, 196), + listOf(1u, 5u) to Rational(-204, 35), + listOf(2u, 5u) to Rational(-307233, 2450), + listOf(3u, 5u) to Rational(-12492, 35), + listOf(4u, 5u) to Rational(4563, 28), + listOf(0u, 6u) to Rational(45, 98), + listOf(1u, 6u) to Rational(54, 7), + listOf(2u, 6u) to Rational(1809, 35), + listOf(3u, 6u) to Rational(162), + listOf(4u, 6u) to Rational(405, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + )), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(7, 3), + listOf(2u) to Rational(-35, 16), + listOf(3u) to Rational(-343, 6), + listOf(4u) to Rational(343, 3), + listOf(0u, 1u) to Rational(-19, 5), + listOf(1u, 1u) to Rational(-823, 120), + listOf(2u, 1u) to Rational(1232417, 6720), + listOf(3u, 1u) to Rational(-9863, 24), + listOf(4u, 1u) to Rational(385, 4), + listOf(0u, 2u) to Rational(2439, 350), + listOf(1u, 2u) to Rational(-5793, 40), + listOf(2u, 2u) to Rational(1172113, 3360), + listOf(3u, 2u) to Rational(-13531, 40), + listOf(4u, 2u) to Rational(2824, 7), + listOf(0u, 3u) to Rational(3417, 700), + listOf(1u, 3u) to Rational(1191, 200), + listOf(2u, 3u) to Rational(8383, 28), + listOf(3u, 3u) to Rational(-220279, 280), + listOf(4u, 3u) to Rational(49179, 196), + listOf(0u, 4u) to Rational(57, 35), + listOf(1u, 4u) to Rational(-33771, 700), + listOf(2u, 4u) to Rational(196279, 1225), + listOf(3u, 4u) to Rational(-32259, 140), + listOf(4u, 4u) to Rational(23868, 49), + listOf(0u, 5u) to Rational(333, 196), + listOf(1u, 5u) to Rational(-204, 35), + listOf(2u, 5u) to Rational(-307233, 2450), + listOf(3u, 5u) to Rational(-12492, 35), + listOf(4u, 5u) to Rational(4563, 28), + listOf(0u, 6u) to Rational(45, 98), + listOf(1u, 6u) to Rational(54, 7), + listOf(2u, 6u) to Rational(1809, 35), + listOf(3u, 6u) to Rational(162), + listOf(4u, 6u) to Rational(405, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-11, 3), + listOf(1u) to Rational(5, 2), + listOf(2u) to Rational(13, 7), + listOf(0u, 1u) to Rational(16, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(6, 1), + listOf(0u, 2u) to Rational(-14, 3), + listOf(1u, 2u) to Rational(-2, 7), + listOf(2u, 2u) to Rational(-10, 8), + ) + )), + "test 5'" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, mapOf( + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-11, 3), + listOf(1u) to Rational(5, 2), + listOf(2u) to Rational(13, 7), + listOf(0u, 1u) to Rational(16, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(6, 1), + listOf(0u, 2u) to Rational(-14, 3), + listOf(1u, 2u) to Rational(-2, 7), + listOf(2u, 2u) to Rational(-10, 8), + ) + )), + "test 6'" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_Polynomial_substitute_RationalFunction_Map() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(4u) to Rational(-194071, 4900), + listOf(3u, 1u) to Rational(394811, 225), + listOf(2u, 2u) to Rational(-444183161, 66150), + listOf(1u, 3u) to Rational(70537618, 59535), + listOf(0u, 4u) to Rational(9655504, 2835), + ), + NumberedPolynomialAsIs( + listOf(4u) to Rational(9, 1), + listOf(3u, 1u) to Rational(61, 1), + listOf(2u, 2u) to Rational(2137, 36), + listOf(1u, 3u) to Rational(-1342, 9), + listOf(0u, 4u) to Rational(484, 9), + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(17, 7), + listOf(0u, 1u) to Rational(-13, 1), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(-18, 6), + listOf(0u, 1u) to Rational(11, 6), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(18, 5), + listOf(0u, 1u) to Rational(-16, 3), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(-4, 1), + ) + ), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-6443599, 10000), + listOf(1u) to Rational(166251223, 210000), + listOf(2u) to Rational(-4606805099, 3528000), + listOf(3u) to Rational(51204379, 19600), + listOf(4u) to Rational(-529045460659, 277830000), + listOf(5u) to Rational(2630836709, 1488375), + listOf(6u) to Rational(-42675691369, 25004700), + listOf(7u) to Rational(495825223, 1250235), + listOf(8u) to Rational(-22531756, 1750329), + listOf(0u, 1u) to Rational(-2526552797, 420000), + listOf(1u, 1u) to Rational(31108840471, 2520000), + listOf(2u, 1u) to Rational(-4789740847, 1102500), + listOf(3u, 1u) to Rational(186594307807, 11340000), + listOf(4u, 1u) to Rational(-11677815943, 1488375), + listOf(5u, 1u) to Rational(-181118486447, 27783000), + listOf(6u, 1u) to Rational(-16123292162, 14586075), + listOf(7u, 1u) to Rational(-140339343808, 26254935), + listOf(8u, 1u) to Rational(4570171616, 5250987), + listOf(0u, 2u) to Rational(-181436530573, 10080000), + listOf(1u, 2u) to Rational(6700437957491, 105840000), + listOf(2u, 2u) to Rational(-3527267461, 1417500), + listOf(3u, 2u) to Rational(-38084563451, 5556600), + listOf(4u, 2u) to Rational(-565662040631, 13891500), + listOf(5u, 2u) to Rational(-35479071126397, 583443000), + listOf(6u, 2u) to Rational(-11717559078469, 525098700), + listOf(7u, 2u) to Rational(-2043385293517, 225042300), + listOf(8u, 2u) to Rational(-3644439630451, 551353635), + listOf(0u, 3u) to Rational(-1760423269, 126000), + listOf(1u, 3u) to Rational(310176758299, 2352000), + listOf(2u, 3u) to Rational(-907229584837, 21168000), + listOf(3u, 3u) to Rational(-16717135885963, 95256000), + listOf(4u, 3u) to Rational(-43762928025353, 333396000), + listOf(5u, 3u) to Rational(-328427480571607, 3000564000), + listOf(6u, 3u) to Rational(-7722675917197, 210039480), + listOf(7u, 3u) to Rational(1713350137019, 1225230300), + listOf(8u, 3u) to Rational(156695935643, 31505922), + listOf(0u, 4u) to Rational(18362364269, 1008000), + listOf(1u, 4u) to Rational(955674858553, 10584000), + listOf(2u, 4u) to Rational(-71937470607371, 444528000), + listOf(3u, 4u) to Rational(-34097985615163, 95256000), + listOf(4u, 4u) to Rational(-340736178775883, 2000376000), + listOf(5u, 4u) to Rational(-511324523441897, 10501974000), + listOf(6u, 4u) to Rational(-125375649409151, 8821658160), + listOf(7u, 4u) to Rational(-2813518533421, 1575296100), + listOf(8u, 4u) to Rational(-17044089109, 5250987), + listOf(0u, 5u) to Rational(600086461, 20160), + listOf(1u, 5u) to Rational(-18959931367, 423360), + listOf(2u, 5u) to Rational(-9178804929607, 44452800), + listOf(3u, 5u) to Rational(-1460114275979, 5334336), + listOf(4u, 5u) to Rational(-342533479090169, 4200789600), + listOf(5u, 5u) to Rational(20335453022963, 4200789600), + listOf(6u, 5u) to Rational(-21649775090197, 6301184400), + listOf(7u, 5u) to Rational(-197301716069, 131274675), + listOf(8u, 5u) to Rational(18711357470, 15752961), + listOf(0u, 6u) to Rational(621417991, 100800), + listOf(1u, 6u) to Rational(-159236792977, 2116800), + listOf(2u, 6u) to Rational(-6602528890883, 66679200), + listOf(3u, 6u) to Rational(-1086091664047, 19051200), + listOf(4u, 6u) to Rational(3769375009003, 1680315840), + listOf(5u, 6u) to Rational(-12920385574769, 1050197400), + listOf(6u, 6u) to Rational(-90219591809287, 6301184400), + listOf(7u, 6u) to Rational(656361553391, 1575296100), + listOf(8u, 6u) to Rational(757900793, 2250423), + listOf(0u, 7u) to Rational(-100770017, 15120), + listOf(1u, 7u) to Rational(-316364851, 17640), + listOf(2u, 7u) to Rational(-85118560057, 6667920), + listOf(3u, 7u) to Rational(6286563719, 416745), + listOf(4u, 7u) to Rational(26803885301, 1714608), + listOf(5u, 7u) to Rational(-13767154393, 4286520), + listOf(6u, 7u) to Rational(-3875138933, 1224720), + listOf(7u, 7u) to Rational(65193755, 333396), + listOf(8u, 7u) to Rational(90974351, 2500470), + listOf(0u, 8u) to Rational(-3182197, 1260), + listOf(1u, 8u) to Rational(24899923, 8820), + listOf(2u, 8u) to Rational(-19999556, 19845), + listOf(3u, 8u) to Rational(3276587, 3969), + listOf(4u, 8u) to Rational(13719549239, 5000940), + listOf(5u, 8u) to Rational(-961839938, 1250235), + listOf(6u, 8u) to Rational(-198184871, 833490), + listOf(7u, 8u) to Rational(230659711, 5000940), + listOf(8u, 8u) to Rational(292447, 35721) + ), + NumberedPolynomialAsIs( + listOf() to Rational(9, 100), + listOf(1u) to Rational(-21, 50), + listOf(2u) to Rational(293, 700), + listOf(3u) to Rational(29, 210), + listOf(4u) to Rational(3233, 8820), + listOf(5u) to Rational(-289, 441), + listOf(6u) to Rational(-1, 9), + listOf(7u) to Rational(-20, 441), + listOf(8u) to Rational(100, 441), + listOf(0u, 1u) to Rational(-57, 80), + listOf(1u, 1u) to Rational(-121, 400), + listOf(2u, 1u) to Rational(37117, 8400), + listOf(3u, 1u) to Rational(-4853, 3150), + listOf(4u, 1u) to Rational(1166203, 132300), + listOf(5u, 1u) to Rational(-2708, 567), + listOf(6u, 1u) to Rational(-287159, 416745), + listOf(7u, 1u) to Rational(-478204, 83349), + listOf(8u, 1u) to Rational(176320, 83349), + listOf(0u, 2u) to Rational(-6239, 6400), + listOf(1u, 2u) to Rational(264211, 11200), + listOf(2u, 2u) to Rational(-1591999, 100800), + listOf(3u, 2u) to Rational(12450091, 529200), + listOf(4u, 2u) to Rational(9230759, 226800), + listOf(5u, 2u) to Rational(18995554, 2083725), + listOf(6u, 2u) to Rational(136706258, 6251175), + listOf(7u, 2u) to Rational(-120907496, 3750705), + listOf(8u, 2u) to Rational(117200176, 15752961), + listOf(0u, 3u) to Rational(5653, 320), + listOf(1u, 3u) to Rational(-130853, 8400), + listOf(2u, 3u) to Rational(-20939327, 151200), + listOf(3u, 3u) to Rational(2566691, 25200), + listOf(4u, 3u) to Rational(-68441519, 476280), + listOf(5u, 3u) to Rational(2462904247, 12502350), + listOf(6u, 3u) to Rational(353667161, 18753525), + listOf(7u, 3u) to Rational(-1689134372, 26254935), + listOf(8u, 3u) to Rational(35084104, 2250423), + listOf(0u, 4u) to Rational(-3587, 300), + listOf(1u, 4u) to Rational(-10513243, 33600), + listOf(2u, 4u) to Rational(30766733, 176400), + listOf(3u, 4u) to Rational(-65680021, 198450), + listOf(4u, 4u) to Rational(-8108910547, 20003760), + listOf(5u, 4u) to Rational(2922125159, 6251175), + listOf(6u, 4u) to Rational(-4245279943, 131274675), + listOf(7u, 4u) to Rational(-371946872, 3750705), + listOf(8u, 4u) to Rational(61286752, 2250423), + listOf(0u, 5u) to Rational(-20477, 160), + listOf(1u, 5u) to Rational(215741, 1120), + listOf(2u, 5u) to Rational(30785843, 31752), + listOf(3u, 5u) to Rational(-357495959, 317520), + listOf(4u, 5u) to Rational(-1611242993, 10001880), + listOf(5u, 5u) to Rational(345925495, 500094), + listOf(6u, 5u) to Rational(-755948411, 3750705), + listOf(7u, 5u) to Rational(-108643496, 1250235), + listOf(8u, 5u) to Rational(1122512, 35721), + listOf(0u, 6u) to Rational(358037, 2880), + listOf(1u, 6u) to Rational(3895837, 3360), + listOf(2u, 6u) to Rational(359419201, 1270080), + listOf(3u, 6u) to Rational(-158522587, 105840), + listOf(4u, 6u) to Rational(10909002599, 20003760), + listOf(5u, 6u) to Rational(76846972, 138915), + listOf(6u, 6u) to Rational(-327696553, 1250235), + listOf(7u, 6u) to Rational(-1687328, 35721), + listOf(8u, 6u) to Rational(1016836, 35721), + listOf(0u, 7u) to Rational(658, 3), + listOf(1u, 7u) to Rational(48035, 168), + listOf(2u, 7u) to Rational(-5777875, 5292), + listOf(3u, 7u) to Rational(-7893899, 10584), + listOf(4u, 7u) to Rational(10191652, 11907), + listOf(5u, 7u) to Rational(2920121, 23814), + listOf(6u, 7u) to Rational(-2699780, 11907), + listOf(7u, 7u) to Rational(4556, 441), + listOf(8u, 7u) to Rational(3440, 189), + listOf(0u, 8u) to Rational(64, 1), + listOf(1u, 8u) to Rational(-808, 7), + listOf(2u, 8u) to Rational(-360895, 1764), + listOf(3u, 8u) to Rational(257657, 882), + listOf(4u, 8u) to Rational(3779917, 15876), + listOf(5u, 8u) to Rational(-610279, 3969), + listOf(6u, 8u) to Rational(-25091, 441), + listOf(7u, 8u) to Rational(9560, 567), + listOf(8u, 8u) to Rational(400, 81) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-6443599, 10000), + listOf(1u) to Rational(166251223, 210000), + listOf(2u) to Rational(-4606805099, 3528000), + listOf(3u) to Rational(51204379, 19600), + listOf(4u) to Rational(-529045460659, 277830000), + listOf(5u) to Rational(2630836709, 1488375), + listOf(6u) to Rational(-42675691369, 25004700), + listOf(7u) to Rational(495825223, 1250235), + listOf(8u) to Rational(-22531756, 1750329), + listOf(0u, 1u) to Rational(-2526552797, 420000), + listOf(1u, 1u) to Rational(31108840471, 2520000), + listOf(2u, 1u) to Rational(-4789740847, 1102500), + listOf(3u, 1u) to Rational(186594307807, 11340000), + listOf(4u, 1u) to Rational(-11677815943, 1488375), + listOf(5u, 1u) to Rational(-181118486447, 27783000), + listOf(6u, 1u) to Rational(-16123292162, 14586075), + listOf(7u, 1u) to Rational(-140339343808, 26254935), + listOf(8u, 1u) to Rational(4570171616, 5250987), + listOf(0u, 2u) to Rational(-181436530573, 10080000), + listOf(1u, 2u) to Rational(6700437957491, 105840000), + listOf(2u, 2u) to Rational(-3527267461, 1417500), + listOf(3u, 2u) to Rational(-38084563451, 5556600), + listOf(4u, 2u) to Rational(-565662040631, 13891500), + listOf(5u, 2u) to Rational(-35479071126397, 583443000), + listOf(6u, 2u) to Rational(-11717559078469, 525098700), + listOf(7u, 2u) to Rational(-2043385293517, 225042300), + listOf(8u, 2u) to Rational(-3644439630451, 551353635), + listOf(0u, 3u) to Rational(-1760423269, 126000), + listOf(1u, 3u) to Rational(310176758299, 2352000), + listOf(2u, 3u) to Rational(-907229584837, 21168000), + listOf(3u, 3u) to Rational(-16717135885963, 95256000), + listOf(4u, 3u) to Rational(-43762928025353, 333396000), + listOf(5u, 3u) to Rational(-328427480571607, 3000564000), + listOf(6u, 3u) to Rational(-7722675917197, 210039480), + listOf(7u, 3u) to Rational(1713350137019, 1225230300), + listOf(8u, 3u) to Rational(156695935643, 31505922), + listOf(0u, 4u) to Rational(18362364269, 1008000), + listOf(1u, 4u) to Rational(955674858553, 10584000), + listOf(2u, 4u) to Rational(-71937470607371, 444528000), + listOf(3u, 4u) to Rational(-34097985615163, 95256000), + listOf(4u, 4u) to Rational(-340736178775883, 2000376000), + listOf(5u, 4u) to Rational(-511324523441897, 10501974000), + listOf(6u, 4u) to Rational(-125375649409151, 8821658160), + listOf(7u, 4u) to Rational(-2813518533421, 1575296100), + listOf(8u, 4u) to Rational(-17044089109, 5250987), + listOf(0u, 5u) to Rational(600086461, 20160), + listOf(1u, 5u) to Rational(-18959931367, 423360), + listOf(2u, 5u) to Rational(-9178804929607, 44452800), + listOf(3u, 5u) to Rational(-1460114275979, 5334336), + listOf(4u, 5u) to Rational(-342533479090169, 4200789600), + listOf(5u, 5u) to Rational(20335453022963, 4200789600), + listOf(6u, 5u) to Rational(-21649775090197, 6301184400), + listOf(7u, 5u) to Rational(-197301716069, 131274675), + listOf(8u, 5u) to Rational(18711357470, 15752961), + listOf(0u, 6u) to Rational(621417991, 100800), + listOf(1u, 6u) to Rational(-159236792977, 2116800), + listOf(2u, 6u) to Rational(-6602528890883, 66679200), + listOf(3u, 6u) to Rational(-1086091664047, 19051200), + listOf(4u, 6u) to Rational(3769375009003, 1680315840), + listOf(5u, 6u) to Rational(-12920385574769, 1050197400), + listOf(6u, 6u) to Rational(-90219591809287, 6301184400), + listOf(7u, 6u) to Rational(656361553391, 1575296100), + listOf(8u, 6u) to Rational(757900793, 2250423), + listOf(0u, 7u) to Rational(-100770017, 15120), + listOf(1u, 7u) to Rational(-316364851, 17640), + listOf(2u, 7u) to Rational(-85118560057, 6667920), + listOf(3u, 7u) to Rational(6286563719, 416745), + listOf(4u, 7u) to Rational(26803885301, 1714608), + listOf(5u, 7u) to Rational(-13767154393, 4286520), + listOf(6u, 7u) to Rational(-3875138933, 1224720), + listOf(7u, 7u) to Rational(65193755, 333396), + listOf(8u, 7u) to Rational(90974351, 2500470), + listOf(0u, 8u) to Rational(-3182197, 1260), + listOf(1u, 8u) to Rational(24899923, 8820), + listOf(2u, 8u) to Rational(-19999556, 19845), + listOf(3u, 8u) to Rational(3276587, 3969), + listOf(4u, 8u) to Rational(13719549239, 5000940), + listOf(5u, 8u) to Rational(-961839938, 1250235), + listOf(6u, 8u) to Rational(-198184871, 833490), + listOf(7u, 8u) to Rational(230659711, 5000940), + listOf(8u, 8u) to Rational(292447, 35721) + ), + NumberedPolynomialAsIs( + listOf() to Rational(9, 100), + listOf(1u) to Rational(-21, 50), + listOf(2u) to Rational(293, 700), + listOf(3u) to Rational(29, 210), + listOf(4u) to Rational(3233, 8820), + listOf(5u) to Rational(-289, 441), + listOf(6u) to Rational(-1, 9), + listOf(7u) to Rational(-20, 441), + listOf(8u) to Rational(100, 441), + listOf(0u, 1u) to Rational(-57, 80), + listOf(1u, 1u) to Rational(-121, 400), + listOf(2u, 1u) to Rational(37117, 8400), + listOf(3u, 1u) to Rational(-4853, 3150), + listOf(4u, 1u) to Rational(1166203, 132300), + listOf(5u, 1u) to Rational(-2708, 567), + listOf(6u, 1u) to Rational(-287159, 416745), + listOf(7u, 1u) to Rational(-478204, 83349), + listOf(8u, 1u) to Rational(176320, 83349), + listOf(0u, 2u) to Rational(-6239, 6400), + listOf(1u, 2u) to Rational(264211, 11200), + listOf(2u, 2u) to Rational(-1591999, 100800), + listOf(3u, 2u) to Rational(12450091, 529200), + listOf(4u, 2u) to Rational(9230759, 226800), + listOf(5u, 2u) to Rational(18995554, 2083725), + listOf(6u, 2u) to Rational(136706258, 6251175), + listOf(7u, 2u) to Rational(-120907496, 3750705), + listOf(8u, 2u) to Rational(117200176, 15752961), + listOf(0u, 3u) to Rational(5653, 320), + listOf(1u, 3u) to Rational(-130853, 8400), + listOf(2u, 3u) to Rational(-20939327, 151200), + listOf(3u, 3u) to Rational(2566691, 25200), + listOf(4u, 3u) to Rational(-68441519, 476280), + listOf(5u, 3u) to Rational(2462904247, 12502350), + listOf(6u, 3u) to Rational(353667161, 18753525), + listOf(7u, 3u) to Rational(-1689134372, 26254935), + listOf(8u, 3u) to Rational(35084104, 2250423), + listOf(0u, 4u) to Rational(-3587, 300), + listOf(1u, 4u) to Rational(-10513243, 33600), + listOf(2u, 4u) to Rational(30766733, 176400), + listOf(3u, 4u) to Rational(-65680021, 198450), + listOf(4u, 4u) to Rational(-8108910547, 20003760), + listOf(5u, 4u) to Rational(2922125159, 6251175), + listOf(6u, 4u) to Rational(-4245279943, 131274675), + listOf(7u, 4u) to Rational(-371946872, 3750705), + listOf(8u, 4u) to Rational(61286752, 2250423), + listOf(0u, 5u) to Rational(-20477, 160), + listOf(1u, 5u) to Rational(215741, 1120), + listOf(2u, 5u) to Rational(30785843, 31752), + listOf(3u, 5u) to Rational(-357495959, 317520), + listOf(4u, 5u) to Rational(-1611242993, 10001880), + listOf(5u, 5u) to Rational(345925495, 500094), + listOf(6u, 5u) to Rational(-755948411, 3750705), + listOf(7u, 5u) to Rational(-108643496, 1250235), + listOf(8u, 5u) to Rational(1122512, 35721), + listOf(0u, 6u) to Rational(358037, 2880), + listOf(1u, 6u) to Rational(3895837, 3360), + listOf(2u, 6u) to Rational(359419201, 1270080), + listOf(3u, 6u) to Rational(-158522587, 105840), + listOf(4u, 6u) to Rational(10909002599, 20003760), + listOf(5u, 6u) to Rational(76846972, 138915), + listOf(6u, 6u) to Rational(-327696553, 1250235), + listOf(7u, 6u) to Rational(-1687328, 35721), + listOf(8u, 6u) to Rational(1016836, 35721), + listOf(0u, 7u) to Rational(658, 3), + listOf(1u, 7u) to Rational(48035, 168), + listOf(2u, 7u) to Rational(-5777875, 5292), + listOf(3u, 7u) to Rational(-7893899, 10584), + listOf(4u, 7u) to Rational(10191652, 11907), + listOf(5u, 7u) to Rational(2920121, 23814), + listOf(6u, 7u) to Rational(-2699780, 11907), + listOf(7u, 7u) to Rational(4556, 441), + listOf(8u, 7u) to Rational(3440, 189), + listOf(0u, 8u) to Rational(64, 1), + listOf(1u, 8u) to Rational(-808, 7), + listOf(2u, 8u) to Rational(-360895, 1764), + listOf(3u, 8u) to Rational(257657, 882), + listOf(4u, 8u) to Rational(3779917, 15876), + listOf(5u, 8u) to Rational(-610279, 3969), + listOf(6u, 8u) to Rational(-25091, 441), + listOf(7u, 8u) to Rational(9560, 567), + listOf(8u, 8u) to Rational(400, 81) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 9), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(10, 9), + listOf(0u, 1u) to Rational(13, 3), + listOf(1u, 1u) to Rational(-12, 4), + listOf(2u, 1u) to Rational(3, 6), + listOf(0u, 2u) to Rational(2, 9), + listOf(1u, 2u) to Rational(7, 3), + listOf(2u, 2u) to Rational(16, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 2), + listOf(1u) to Rational(6, 2), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 1), + listOf(1u, 1u) to Rational(-11, 3), + listOf(2u, 1u) to Rational(7, 5), + listOf(0u, 2u) to Rational(8, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(17, 4), + ) + ) + )), + "test 3'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-66677, 3500), + listOf(1u) to Rational(-206281, 10500), + listOf(2u) to Rational(-412567, 7056), + listOf(3u) to Rational(-310081, 11025), + listOf(4u) to Rational(-575996, 15435), + listOf(0u, 1u) to Rational(-573701, 4200), + listOf(1u, 1u) to Rational(-2239001, 25200), + listOf(2u, 1u) to Rational(-8817889, 132300), + listOf(3u, 1u) to Rational(2317919, 44100), + listOf(4u, 1u) to Rational(1169471, 6615), + listOf(0u, 2u) to Rational(-4057819, 33600), + listOf(1u, 2u) to Rational(1373311, 12600), + listOf(2u, 2u) to Rational(32433493, 52920), + listOf(3u, 2u) to Rational(4998053, 33075), + listOf(4u, 2u) to Rational(-2147779, 8820), + listOf(0u, 3u) to Rational(2018481, 2240), + listOf(1u, 3u) to Rational(941713, 1440), + listOf(2u, 3u) to Rational(183749, 6615), + listOf(3u, 3u) to Rational(-4631023, 15876), + listOf(4u, 3u) to Rational(25609336, 178605), + listOf(0u, 4u) to Rational(11886431, 6720), + listOf(1u, 4u) to Rational(18433, 504), + listOf(2u, 4u) to Rational(-39613331, 45360), + listOf(3u, 4u) to Rational(681619, 5670), + listOf(4u, 4u) to Rational(-864841, 20412), + listOf(0u, 5u) to Rational(343535, 1008), + listOf(1u, 5u) to Rational(-33583, 72), + listOf(2u, 5u) to Rational(1194625, 9072), + listOf(3u, 5u) to Rational(-62917, 2268), + listOf(4u, 5u) to Rational(157645, 10206), + listOf(0u, 6u) to Rational(-1381, 3), + listOf(1u, 6u) to Rational(919, 36), + listOf(2u, 6u) to Rational(-3053, 36), + listOf(3u, 6u) to Rational(2125, 324), + listOf(4u, 6u) to Rational(-236, 243) + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(1, 4), + listOf(1u) to Rational(-5, 3), + listOf(2u) to Rational(35, 9), + listOf(3u) to Rational(-100, 27), + listOf(4u) to Rational(100, 81), + listOf(0u, 1u) to Rational(-5, 3), + listOf(1u, 1u) to Rational(14, 9), + listOf(2u, 1u) to Rational(1874, 189), + listOf(3u, 1u) to Rational(-620, 63), + listOf(4u, 1u) to Rational(40, 63), + listOf(0u, 2u) to Rational(16, 9), + listOf(1u, 2u) to Rational(365, 21), + listOf(2u, 2u) to Rational(112, 9), + listOf(3u, 2u) to Rational(-464, 63), + listOf(4u, 2u) to Rational(1996, 441), + listOf(0u, 3u) to Rational(10, 3), + listOf(1u, 3u) to Rational(118, 21), + listOf(2u, 3u) to Rational(-272, 21), + listOf(3u, 3u) to Rational(-764, 49), + listOf(4u, 3u) to Rational(8, 7), + listOf(0u, 4u) to Rational(1, 1), + listOf(1u, 4u) to Rational(-10, 7), + listOf(2u, 4u) to Rational(-171, 49), + listOf(3u, 4u) to Rational(20, 7), + listOf(4u, 4u) to Rational(4, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-66677, 3500), + listOf(1u) to Rational(-206281, 10500), + listOf(2u) to Rational(-412567, 7056), + listOf(3u) to Rational(-310081, 11025), + listOf(4u) to Rational(-575996, 15435), + listOf(0u, 1u) to Rational(-573701, 4200), + listOf(1u, 1u) to Rational(-2239001, 25200), + listOf(2u, 1u) to Rational(-8817889, 132300), + listOf(3u, 1u) to Rational(2317919, 44100), + listOf(4u, 1u) to Rational(1169471, 6615), + listOf(0u, 2u) to Rational(-4057819, 33600), + listOf(1u, 2u) to Rational(1373311, 12600), + listOf(2u, 2u) to Rational(32433493, 52920), + listOf(3u, 2u) to Rational(4998053, 33075), + listOf(4u, 2u) to Rational(-2147779, 8820), + listOf(0u, 3u) to Rational(2018481, 2240), + listOf(1u, 3u) to Rational(941713, 1440), + listOf(2u, 3u) to Rational(183749, 6615), + listOf(3u, 3u) to Rational(-4631023, 15876), + listOf(4u, 3u) to Rational(25609336, 178605), + listOf(0u, 4u) to Rational(11886431, 6720), + listOf(1u, 4u) to Rational(18433, 504), + listOf(2u, 4u) to Rational(-39613331, 45360), + listOf(3u, 4u) to Rational(681619, 5670), + listOf(4u, 4u) to Rational(-864841, 20412), + listOf(0u, 5u) to Rational(343535, 1008), + listOf(1u, 5u) to Rational(-33583, 72), + listOf(2u, 5u) to Rational(1194625, 9072), + listOf(3u, 5u) to Rational(-62917, 2268), + listOf(4u, 5u) to Rational(157645, 10206), + listOf(0u, 6u) to Rational(-1381, 3), + listOf(1u, 6u) to Rational(919, 36), + listOf(2u, 6u) to Rational(-3053, 36), + listOf(3u, 6u) to Rational(2125, 324), + listOf(4u, 6u) to Rational(-236, 243) + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(1, 4), + listOf(1u) to Rational(-5, 3), + listOf(2u) to Rational(35, 9), + listOf(3u) to Rational(-100, 27), + listOf(4u) to Rational(100, 81), + listOf(0u, 1u) to Rational(-5, 3), + listOf(1u, 1u) to Rational(14, 9), + listOf(2u, 1u) to Rational(1874, 189), + listOf(3u, 1u) to Rational(-620, 63), + listOf(4u, 1u) to Rational(40, 63), + listOf(0u, 2u) to Rational(16, 9), + listOf(1u, 2u) to Rational(365, 21), + listOf(2u, 2u) to Rational(112, 9), + listOf(3u, 2u) to Rational(-464, 63), + listOf(4u, 2u) to Rational(1996, 441), + listOf(0u, 3u) to Rational(10, 3), + listOf(1u, 3u) to Rational(118, 21), + listOf(2u, 3u) to Rational(-272, 21), + listOf(3u, 3u) to Rational(-764, 49), + listOf(4u, 3u) to Rational(8, 7), + listOf(0u, 4u) to Rational(1, 1), + listOf(1u, 4u) to Rational(-10, 7), + listOf(2u, 4u) to Rational(-171, 49), + listOf(3u, 4u) to Rational(20, 7), + listOf(4u, 4u) to Rational(4, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 9), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(10, 9), + listOf(0u, 1u) to Rational(13, 3), + listOf(1u, 1u) to Rational(-12, 4), + listOf(2u, 1u) to Rational(3, 6), + listOf(0u, 2u) to Rational(2, 9), + listOf(1u, 2u) to Rational(7, 3), + listOf(2u, 2u) to Rational(16, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 2), + listOf(1u) to Rational(6, 2), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 1), + listOf(1u, 1u) to Rational(-11, 3), + listOf(2u, 1u) to Rational(7, 5), + listOf(0u, 2u) to Rational(8, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(17, 4), + ) + ) + )), + "test 4'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(3539, 700), + listOf(1u) to Rational(-307079, 6300), + listOf(2u) to Rational(451609, 15120), + listOf(3u) to Rational(35287733, 396900), + listOf(4u) to Rational(-37242617, 396900), + listOf(5u) to Rational(382747, 19845), + listOf(6u) to Rational(-2407, 3969), + listOf(0u, 1u) to Rational(-226, 175), + listOf(1u, 1u) to Rational(-74113, 1890), + listOf(2u, 1u) to Rational(250931, 1764), + listOf(3u, 1u) to Rational(30071473, 99225), + listOf(4u, 1u) to Rational(-286466, 1323), + listOf(5u, 1u) to Rational(-2285282, 9261), + listOf(6u, 1u) to Rational(17900, 441), + listOf(0u, 2u) to Rational(3817, 3150), + listOf(1u, 2u) to Rational(577568, 11025), + listOf(2u, 2u) to Rational(9073553, 99225), + listOf(3u, 2u) to Rational(-1415849, 79380), + listOf(4u, 2u) to Rational(-124715629, 277830), + listOf(5u, 2u) to Rational(-1328953, 1890), + listOf(6u, 2u) to Rational(-297148, 1323), + listOf(0u, 3u) to Rational(6043, 945), + listOf(1u, 3u) to Rational(160381, 6615), + listOf(2u, 3u) to Rational(-673249, 13230), + listOf(3u, 3u) to Rational(-319255, 2058), + listOf(4u, 3u) to Rational(-98144, 1029), + listOf(5u, 3u) to Rational(-320239, 5145), + listOf(6u, 3u) to Rational(400, 147), + listOf(0u, 4u) to Rational(163, 63), + listOf(1u, 4u) to Rational(-25183, 4410), + listOf(2u, 4u) to Rational(-21369, 1372), + listOf(3u, 4u) to Rational(127499, 30870), + listOf(4u, 4u) to Rational(86971, 12348), + listOf(5u, 4u) to Rational(-11129, 1470), + listOf(6u, 4u) to Rational(544, 147) + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(1, 4), + listOf(1u) to Rational(-5, 3), + listOf(2u) to Rational(35, 9), + listOf(3u) to Rational(-100, 27), + listOf(4u) to Rational(100, 81), + listOf(0u, 1u) to Rational(-5, 3), + listOf(1u, 1u) to Rational(14, 9), + listOf(2u, 1u) to Rational(1874, 189), + listOf(3u, 1u) to Rational(-620, 63), + listOf(4u, 1u) to Rational(40, 63), + listOf(0u, 2u) to Rational(16, 9), + listOf(1u, 2u) to Rational(365, 21), + listOf(2u, 2u) to Rational(112, 9), + listOf(3u, 2u) to Rational(-464, 63), + listOf(4u, 2u) to Rational(1996, 441), + listOf(0u, 3u) to Rational(10, 3), + listOf(1u, 3u) to Rational(118, 21), + listOf(2u, 3u) to Rational(-272, 21), + listOf(3u, 3u) to Rational(-764, 49), + listOf(4u, 3u) to Rational(8, 7), + listOf(0u, 4u) to Rational(1, 1), + listOf(1u, 4u) to Rational(-10, 7), + listOf(2u, 4u) to Rational(-171, 49), + listOf(3u, 4u) to Rational(20, 7), + listOf(4u, 4u) to Rational(4, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(3539, 700), + listOf(1u) to Rational(-307079, 6300), + listOf(2u) to Rational(451609, 15120), + listOf(3u) to Rational(35287733, 396900), + listOf(4u) to Rational(-37242617, 396900), + listOf(5u) to Rational(382747, 19845), + listOf(6u) to Rational(-2407, 3969), + listOf(0u, 1u) to Rational(-226, 175), + listOf(1u, 1u) to Rational(-74113, 1890), + listOf(2u, 1u) to Rational(250931, 1764), + listOf(3u, 1u) to Rational(30071473, 99225), + listOf(4u, 1u) to Rational(-286466, 1323), + listOf(5u, 1u) to Rational(-2285282, 9261), + listOf(6u, 1u) to Rational(17900, 441), + listOf(0u, 2u) to Rational(3817, 3150), + listOf(1u, 2u) to Rational(577568, 11025), + listOf(2u, 2u) to Rational(9073553, 99225), + listOf(3u, 2u) to Rational(-1415849, 79380), + listOf(4u, 2u) to Rational(-124715629, 277830), + listOf(5u, 2u) to Rational(-1328953, 1890), + listOf(6u, 2u) to Rational(-297148, 1323), + listOf(0u, 3u) to Rational(6043, 945), + listOf(1u, 3u) to Rational(160381, 6615), + listOf(2u, 3u) to Rational(-673249, 13230), + listOf(3u, 3u) to Rational(-319255, 2058), + listOf(4u, 3u) to Rational(-98144, 1029), + listOf(5u, 3u) to Rational(-320239, 5145), + listOf(6u, 3u) to Rational(400, 147), + listOf(0u, 4u) to Rational(163, 63), + listOf(1u, 4u) to Rational(-25183, 4410), + listOf(2u, 4u) to Rational(-21369, 1372), + listOf(3u, 4u) to Rational(127499, 30870), + listOf(4u, 4u) to Rational(86971, 12348), + listOf(5u, 4u) to Rational(-11129, 1470), + listOf(6u, 4u) to Rational(544, 147) + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(1, 4), + listOf(1u) to Rational(-5, 3), + listOf(2u) to Rational(35, 9), + listOf(3u) to Rational(-100, 27), + listOf(4u) to Rational(100, 81), + listOf(0u, 1u) to Rational(-5, 3), + listOf(1u, 1u) to Rational(14, 9), + listOf(2u, 1u) to Rational(1874, 189), + listOf(3u, 1u) to Rational(-620, 63), + listOf(4u, 1u) to Rational(40, 63), + listOf(0u, 2u) to Rational(16, 9), + listOf(1u, 2u) to Rational(365, 21), + listOf(2u, 2u) to Rational(112, 9), + listOf(3u, 2u) to Rational(-464, 63), + listOf(4u, 2u) to Rational(1996, 441), + listOf(0u, 3u) to Rational(10, 3), + listOf(1u, 3u) to Rational(118, 21), + listOf(2u, 3u) to Rational(-272, 21), + listOf(3u, 3u) to Rational(-764, 49), + listOf(4u, 3u) to Rational(8, 7), + listOf(0u, 4u) to Rational(1, 1), + listOf(1u, 4u) to Rational(-10, 7), + listOf(2u, 4u) to Rational(-171, 49), + listOf(3u, 4u) to Rational(20, 7), + listOf(4u, 4u) to Rational(4, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 9), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(10, 9), + listOf(0u, 1u) to Rational(13, 3), + listOf(1u, 1u) to Rational(-12, 4), + listOf(2u, 1u) to Rational(3, 6), + listOf(0u, 2u) to Rational(2, 9), + listOf(1u, 2u) to Rational(7, 3), + listOf(2u, 2u) to Rational(16, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 2), + listOf(1u) to Rational(6, 2), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 1), + listOf(1u, 1u) to Rational(-11, 3), + listOf(2u, 1u) to Rational(7, 5), + listOf(0u, 2u) to Rational(8, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(17, 4), + ) + ) + )), + "test 5'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(0, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(0, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, mapOf( + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 9), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(10, 9), + listOf(0u, 1u) to Rational(13, 3), + listOf(1u, 1u) to Rational(-12, 4), + listOf(2u, 1u) to Rational(3, 6), + listOf(0u, 2u) to Rational(2, 9), + listOf(1u, 2u) to Rational(7, 3), + listOf(2u, 2u) to Rational(16, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 2), + listOf(1u) to Rational(6, 2), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 1), + listOf(1u, 1u) to Rational(-11, 3), + listOf(2u, 1u) to Rational(7, 5), + listOf(0u, 2u) to Rational(8, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(17, 4), + ) + ) + )), + "test 6'" + ) + } + @Test + fun test_RationalFunction_substitute_Double_Map() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs(emptyList() to 0.0), + NumberedPolynomialAsIs(emptyList() to 1.0), + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ), + NumberedPolynomialAsIs( + listOf() to 1.0, + ) + ).substitute(mapOf( + 0 to 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf()), + 0.001, + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 5 to 0.9211194782050933 + )), + 0.001, + "test 2'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 151.1502229133916, + listOf(0u, 1u) to -262.3790170577034, + listOf(0u, 2u) to 102.5097937392923, + ), + NumberedPolynomialAsIs( + listOf() to -367.9969733169944, + listOf(0u, 1u) to 112.4911133334554, + listOf(0u, 2u) to -469.755906895345, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 0 to -8.11707689492641, + )), + 0.001, + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 151.1502229133916, + listOf(0u, 1u) to -262.3790170577034, + listOf(0u, 2u) to 102.5097937392923, + ), + NumberedPolynomialAsIs( + listOf() to -367.9969733169944, + listOf(0u, 1u) to 112.4911133334554, + listOf(0u, 2u) to -469.755906895345, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 0 to -8.11707689492641, + 5 to 0.9211194782050933 + )), + 0.001, + "test 3'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 14.24074356896978, + listOf(1u) to -17.71987055153461, + listOf(2u) to -2.288056483312383, + ), + NumberedPolynomialAsIs( + listOf() to 7.480604285873397, + listOf(1u) to -8.43478016688617, + listOf(2u) to -9.88934943900592, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 1 to 0.795265651276015, + )), + 0.001, + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 14.24074356896978, + listOf(1u) to -17.71987055153461, + listOf(2u) to -2.288056483312383, + ), + NumberedPolynomialAsIs( + listOf() to 7.480604285873397, + listOf(1u) to -8.43478016688617, + listOf(2u) to -9.88934943900592, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 1 to 0.795265651276015, + 5 to 0.9211194782050933 + )), + 0.001, + "test 4'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 7.321261307532708, + ), + NumberedPolynomialAsIs( + listOf() to -575.6325831127576, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 0 to -8.11707689492641, + 1 to 0.795265651276015, + )), + 0.001, + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 7.321261307532708, + ), + NumberedPolynomialAsIs( + listOf() to -575.6325831127576, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(mapOf( + 0 to -8.11707689492641, + 1 to 0.795265651276015, + 5 to 0.9211194782050933 + )), + 0.001, + "test 5'" + ) + } + @Test + fun test_RationalFunction_substitute_Constant_Map() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ).substitute(RationalField, mapOf( + 0 to Rational(1) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(22047, 2450), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2204953, 147000), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 0 to Rational(7, 5), + 1 to Rational(-13, 7), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(22047, 2450), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2204953, 147000), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 0 to Rational(7, 5), + 1 to Rational(-13, 7), + 5 to Rational(-16, 4), + )), + "test 2'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(4191, 490), + listOf(1u) to Rational(14975, 1176), + listOf(2u) to Rational(-10429, 1176) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-775, 147), + listOf(1u) to Rational(-155, 49), + listOf(2u) to Rational(-757, 280) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 1 to Rational(-13, 7), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(4191, 490), + listOf(1u) to Rational(14975, 1176), + listOf(2u) to Rational(-10429, 1176) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-775, 147), + listOf(1u) to Rational(-155, 49), + listOf(2u) to Rational(-757, 280) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 1 to Rational(-13, 7), + 5 to Rational(-16, 4), + )), + "test 3'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-939, 200), + listOf(0u, 1u) to Rational(123, 50), + listOf(0u, 2u) to Rational(1059, 200) + ), + NumberedPolynomialAsIs( + listOf() to Rational(121, 25), + listOf(0u, 1u) to Rational(-949, 375), + listOf(0u, 2u) to Rational(-1423, 200) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 0 to Rational(7, 5), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-939, 200), + listOf(0u, 1u) to Rational(123, 50), + listOf(0u, 2u) to Rational(1059, 200) + ), + NumberedPolynomialAsIs( + listOf() to Rational(121, 25), + listOf(0u, 1u) to Rational(-949, 375), + listOf(0u, 2u) to Rational(-1423, 200) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 0 to Rational(7, 5), + 5 to Rational(-16, 4), + )), + "test 4'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf()), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, mapOf( + 5 to Rational(-16, 4), + )), + "test 5'" + ) + } + @Test + fun test_RationalFunction_substitute_Polynomial_Map() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(211, 4), + listOf(2u) to Rational(88, 3), + listOf(3u) to Rational(-63, 8), + listOf(4u) to Rational(441, 16), + listOf(0u, 1u) to Rational(-671, 15), + listOf(1u, 1u) to Rational(-551, 21), + listOf(2u, 1u) to Rational(279, 25), + listOf(3u, 1u) to Rational(231, 20), + listOf(0u, 2u) to Rational(-1436, 1575), + listOf(1u, 2u) to Rational(2471, 250), + listOf(2u, 2u) to Rational(-4919, 100), + listOf(0u, 3u) to Rational(-1464, 125), + listOf(1u, 3u) to Rational(-264, 25), + listOf(0u, 4u) to Rational(576, 25), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(-9, 4), + listOf(2u) to Rational(943, 8), + listOf(3u) to Rational(117, 8), + listOf(4u) to Rational(147, 16), + listOf(0u, 1u) to Rational(289, 90), + listOf(1u, 1u) to Rational(-2692, 15), + listOf(2u, 1u) to Rational(-1629, 140), + listOf(3u, 1u) to Rational(77, 20), + listOf(0u, 2u) to Rational(6187, 75), + listOf(1u, 2u) to Rational(-2879, 175), + listOf(2u, 2u) to Rational(-4919, 300), + listOf(0u, 3u) to Rational(336, 25), + listOf(1u, 3u) to Rational(-88, 25), + listOf(0u, 4u) to Rational(192, 25), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf(1u) to Rational(3, 2), + listOf(0u, 1u) to Rational(8, 5), + ), + 1 to NumberedPolynomialAsIs( + listOf(1u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-3, 1), + ) + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1202861, 210), + listOf(1u) to Rational(-215117, 45), + listOf(2u) to Rational(10889651, 19845), + listOf(3u) to Rational(-3503956, 6615), + listOf(4u) to Rational(809066, 2205), + listOf(5u) to Rational(-9056, 735), + listOf(6u) to Rational(5396, 315), + listOf(7u) to Rational(-752, 147), + listOf(8u) to Rational(16, 49), + listOf(0u, 1u) to Rational(1738469, 1470), + listOf(1u, 1u) to Rational(-926238703, 52920), + listOf(2u, 1u) to Rational(-44113982, 6615), + listOf(3u, 1u) to Rational(10423519, 5292), + listOf(4u, 1u) to Rational(3769712, 2205), + listOf(5u, 1u) to Rational(8905046, 6615), + listOf(6u, 1u) to Rational(1186972, 6615), + listOf(7u, 1u) to Rational(22124, 441), + listOf(8u, 1u) to Rational(-1504, 147), + listOf(0u, 2u) to Rational(-54723628, 2205), + listOf(1u, 2u) to Rational(70109407, 1323), + listOf(2u, 2u) to Rational(151072591, 17640), + listOf(3u, 2u) to Rational(1216428107, 52920), + listOf(4u, 2u) to Rational(2587873193, 317520), + listOf(5u, 2u) to Rational(393536369, 79380), + listOf(6u, 2u) to Rational(137614937, 79380), + listOf(7u, 2u) to Rational(566866, 1323), + listOf(8u, 2u) to Rational(41848, 441), + listOf(0u, 3u) to Rational(-19470406, 2205), + listOf(1u, 3u) to Rational(72514195, 882), + listOf(2u, 3u) to Rational(-78090707, 1764), + listOf(3u, 3u) to Rational(-1988237707, 26460), + listOf(4u, 3u) to Rational(-802137919, 17640), + listOf(5u, 3u) to Rational(-139989463, 5880), + listOf(6u, 3u) to Rational(-26066641, 3780), + listOf(7u, 3u) to Rational(-2363369, 1323), + listOf(8u, 3u) to Rational(-108280, 441), + listOf(0u, 4u) to Rational(14878516, 441), + listOf(1u, 4u) to Rational(-253416724, 2205), + listOf(2u, 4u) to Rational(16699157, 840), + listOf(3u, 4u) to Rational(-105220979, 13230), + listOf(4u, 4u) to Rational(208266383, 5880), + listOf(5u, 4u) to Rational(650135309, 26460), + listOf(6u, 4u) to Rational(123808663, 11760), + listOf(7u, 4u) to Rational(8563385, 2646), + listOf(8u, 4u) to Rational(19721, 49), + listOf(0u, 5u) to Rational(675645, 49), + listOf(1u, 5u) to Rational(-70554077, 588), + listOf(2u, 5u) to Rational(157884029, 980), + listOf(3u, 5u) to Rational(489548623, 4410), + listOf(4u, 5u) to Rational(148540519, 17640), + listOf(5u, 5u) to Rational(-5559551, 392), + listOf(6u, 5u) to Rational(-18335711, 1470), + listOf(7u, 5u) to Rational(-38437, 9), + listOf(8u, 5u) to Rational(-29620, 63), + listOf(0u, 6u) to Rational(-727625, 49), + listOf(1u, 6u) to Rational(7046685, 98), + listOf(2u, 6u) to Rational(-334814231, 7056), + listOf(3u, 6u) to Rational(-243971737, 17640), + listOf(4u, 6u) to Rational(-571116659, 35280), + listOf(5u, 6u) to Rational(567538, 315), + listOf(6u, 6u) to Rational(3199768, 315), + listOf(7u, 6u) to Rational(227744, 63), + listOf(8u, 6u) to Rational(23116, 63), + listOf(0u, 7u) to Rational(-27500, 7), + listOf(1u, 7u) to Rational(120125, 3), + listOf(2u, 7u) to Rational(-279200, 3), + listOf(3u, 7u) to Rational(-100160, 7), + listOf(4u, 7u) to Rational(920452, 21), + listOf(5u, 7u) to Rational(226481, 21), + listOf(6u, 7u) to Rational(-34428, 7), + listOf(7u, 7u) to Rational(-6232, 3), + listOf(8u, 7u) to Rational(-608, 3), + listOf(0u, 8u) to Rational(2500, 1), + listOf(1u, 8u) to Rational(-19000, 1), + listOf(2u, 8u) to Rational(37900, 1), + listOf(3u, 8u) to Rational(-1840, 1), + listOf(4u, 8u) to Rational(-17876, 1), + listOf(5u, 8u) to Rational(-1240, 1), + listOf(6u, 8u) to Rational(2788, 1), + listOf(7u, 8u) to Rational(800, 1), + listOf(8u, 8u) to Rational(64, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(162487, 63), + listOf(1u) to Rational(-92713, 54), + listOf(2u) to Rational(802436, 1323), + listOf(3u) to Rational(-55088, 441), + listOf(4u) to Rational(1404034, 9261), + listOf(5u) to Rational(-5804, 1029), + listOf(6u) to Rational(51556, 9261), + listOf(7u) to Rational(-752, 441), + listOf(8u) to Rational(16, 147), + listOf(0u, 1u) to Rational(296071, 441), + listOf(1u, 1u) to Rational(-4991281, 882), + listOf(2u, 1u) to Rational(-18702811, 9261), + listOf(3u, 1u) to Rational(40759043, 27783), + listOf(4u, 1u) to Rational(19768501, 27783), + listOf(5u, 1u) to Rational(14307337, 27783), + listOf(6u, 1u) to Rational(1655684, 27783), + listOf(7u, 1u) to Rational(22124, 1323), + listOf(8u, 1u) to Rational(-1504, 441), + listOf(0u, 2u) to Rational(-27667474, 3087), + listOf(1u, 2u) to Rational(265605901, 12348), + listOf(2u, 2u) to Rational(160360775, 98784), + listOf(3u, 2u) to Rational(1169992093, 148176), + listOf(4u, 2u) to Rational(3978014077, 1333584), + listOf(5u, 2u) to Rational(567058123, 333396), + listOf(6u, 2u) to Rational(205132579, 333396), + listOf(7u, 2u) to Rational(566866, 3969), + listOf(8u, 2u) to Rational(41848, 1323), + listOf(0u, 3u) to Rational(-2228822, 1029), + listOf(1u, 3u) to Rational(80179390, 3087), + listOf(2u, 3u) to Rational(-1378630487, 74088), + listOf(3u, 3u) to Rational(-3385811693, 111132), + listOf(4u, 3u) to Rational(-820686977, 49392), + listOf(5u, 3u) to Rational(-89101027, 10584), + listOf(6u, 3u) to Rational(-37847387, 15876), + listOf(7u, 3u) to Rational(-2363369, 3969), + listOf(8u, 3u) to Rational(-108280, 1323), + listOf(0u, 4u) to Rational(12619982, 1029), + listOf(1u, 4u) to Rational(-277723177, 6174), + listOf(2u, 4u) to Rational(649414169, 49392), + listOf(3u, 4u) to Rational(14457595, 63504), + listOf(4u, 4u) to Rational(139270339, 10584), + listOf(5u, 4u) to Rational(140367961, 15876), + listOf(6u, 4u) to Rational(25467083, 7056), + listOf(7u, 4u) to Rational(8563385, 7938), + listOf(8u, 4u) to Rational(19721, 147), + listOf(0u, 5u) to Rational(643850, 147), + listOf(1u, 5u) to Rational(-11818025, 294), + listOf(2u, 5u) to Rational(33963203, 588), + listOf(3u, 5u) to Rational(207216235, 5292), + listOf(4u, 5u) to Rational(2861021, 1512), + listOf(5u, 5u) to Rational(-6302335, 1176), + listOf(6u, 5u) to Rational(-3738587, 882), + listOf(7u, 5u) to Rational(-38437, 27), + listOf(8u, 5u) to Rational(-29620, 189), + listOf(0u, 6u) to Rational(-248725, 49), + listOf(1u, 6u) to Rational(2478535, 98), + listOf(2u, 6u) to Rational(-399721367, 21168), + listOf(3u, 6u) to Rational(-54309317, 10584), + listOf(4u, 6u) to Rational(-95398327, 21168), + listOf(5u, 6u) to Rational(173750, 189), + listOf(6u, 6u) to Rational(92216, 27), + listOf(7u, 6u) to Rational(227744, 189), + listOf(8u, 6u) to Rational(23116, 189), + listOf(0u, 7u) to Rational(-27500, 21), + listOf(1u, 7u) to Rational(120125, 9), + listOf(2u, 7u) to Rational(-279200, 9), + listOf(3u, 7u) to Rational(-100160, 21), + listOf(4u, 7u) to Rational(920452, 63), + listOf(5u, 7u) to Rational(226481, 63), + listOf(6u, 7u) to Rational(-11476, 7), + listOf(7u, 7u) to Rational(-6232, 9), + listOf(8u, 7u) to Rational(-608, 9), + listOf(0u, 8u) to Rational(2500, 3), + listOf(1u, 8u) to Rational(-19000, 3), + listOf(2u, 8u) to Rational(37900, 3), + listOf(3u, 8u) to Rational(-1840, 3), + listOf(4u, 8u) to Rational(-17876, 3), + listOf(5u, 8u) to Rational(-1240, 3), + listOf(6u, 8u) to Rational(2788, 3), + listOf(7u, 8u) to Rational(800, 3), + listOf(8u, 8u) to Rational(64, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + 1 to NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1202861, 210), + listOf(1u) to Rational(-215117, 45), + listOf(2u) to Rational(10889651, 19845), + listOf(3u) to Rational(-3503956, 6615), + listOf(4u) to Rational(809066, 2205), + listOf(5u) to Rational(-9056, 735), + listOf(6u) to Rational(5396, 315), + listOf(7u) to Rational(-752, 147), + listOf(8u) to Rational(16, 49), + listOf(0u, 1u) to Rational(1738469, 1470), + listOf(1u, 1u) to Rational(-926238703, 52920), + listOf(2u, 1u) to Rational(-44113982, 6615), + listOf(3u, 1u) to Rational(10423519, 5292), + listOf(4u, 1u) to Rational(3769712, 2205), + listOf(5u, 1u) to Rational(8905046, 6615), + listOf(6u, 1u) to Rational(1186972, 6615), + listOf(7u, 1u) to Rational(22124, 441), + listOf(8u, 1u) to Rational(-1504, 147), + listOf(0u, 2u) to Rational(-54723628, 2205), + listOf(1u, 2u) to Rational(70109407, 1323), + listOf(2u, 2u) to Rational(151072591, 17640), + listOf(3u, 2u) to Rational(1216428107, 52920), + listOf(4u, 2u) to Rational(2587873193, 317520), + listOf(5u, 2u) to Rational(393536369, 79380), + listOf(6u, 2u) to Rational(137614937, 79380), + listOf(7u, 2u) to Rational(566866, 1323), + listOf(8u, 2u) to Rational(41848, 441), + listOf(0u, 3u) to Rational(-19470406, 2205), + listOf(1u, 3u) to Rational(72514195, 882), + listOf(2u, 3u) to Rational(-78090707, 1764), + listOf(3u, 3u) to Rational(-1988237707, 26460), + listOf(4u, 3u) to Rational(-802137919, 17640), + listOf(5u, 3u) to Rational(-139989463, 5880), + listOf(6u, 3u) to Rational(-26066641, 3780), + listOf(7u, 3u) to Rational(-2363369, 1323), + listOf(8u, 3u) to Rational(-108280, 441), + listOf(0u, 4u) to Rational(14878516, 441), + listOf(1u, 4u) to Rational(-253416724, 2205), + listOf(2u, 4u) to Rational(16699157, 840), + listOf(3u, 4u) to Rational(-105220979, 13230), + listOf(4u, 4u) to Rational(208266383, 5880), + listOf(5u, 4u) to Rational(650135309, 26460), + listOf(6u, 4u) to Rational(123808663, 11760), + listOf(7u, 4u) to Rational(8563385, 2646), + listOf(8u, 4u) to Rational(19721, 49), + listOf(0u, 5u) to Rational(675645, 49), + listOf(1u, 5u) to Rational(-70554077, 588), + listOf(2u, 5u) to Rational(157884029, 980), + listOf(3u, 5u) to Rational(489548623, 4410), + listOf(4u, 5u) to Rational(148540519, 17640), + listOf(5u, 5u) to Rational(-5559551, 392), + listOf(6u, 5u) to Rational(-18335711, 1470), + listOf(7u, 5u) to Rational(-38437, 9), + listOf(8u, 5u) to Rational(-29620, 63), + listOf(0u, 6u) to Rational(-727625, 49), + listOf(1u, 6u) to Rational(7046685, 98), + listOf(2u, 6u) to Rational(-334814231, 7056), + listOf(3u, 6u) to Rational(-243971737, 17640), + listOf(4u, 6u) to Rational(-571116659, 35280), + listOf(5u, 6u) to Rational(567538, 315), + listOf(6u, 6u) to Rational(3199768, 315), + listOf(7u, 6u) to Rational(227744, 63), + listOf(8u, 6u) to Rational(23116, 63), + listOf(0u, 7u) to Rational(-27500, 7), + listOf(1u, 7u) to Rational(120125, 3), + listOf(2u, 7u) to Rational(-279200, 3), + listOf(3u, 7u) to Rational(-100160, 7), + listOf(4u, 7u) to Rational(920452, 21), + listOf(5u, 7u) to Rational(226481, 21), + listOf(6u, 7u) to Rational(-34428, 7), + listOf(7u, 7u) to Rational(-6232, 3), + listOf(8u, 7u) to Rational(-608, 3), + listOf(0u, 8u) to Rational(2500, 1), + listOf(1u, 8u) to Rational(-19000, 1), + listOf(2u, 8u) to Rational(37900, 1), + listOf(3u, 8u) to Rational(-1840, 1), + listOf(4u, 8u) to Rational(-17876, 1), + listOf(5u, 8u) to Rational(-1240, 1), + listOf(6u, 8u) to Rational(2788, 1), + listOf(7u, 8u) to Rational(800, 1), + listOf(8u, 8u) to Rational(64, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(162487, 63), + listOf(1u) to Rational(-92713, 54), + listOf(2u) to Rational(802436, 1323), + listOf(3u) to Rational(-55088, 441), + listOf(4u) to Rational(1404034, 9261), + listOf(5u) to Rational(-5804, 1029), + listOf(6u) to Rational(51556, 9261), + listOf(7u) to Rational(-752, 441), + listOf(8u) to Rational(16, 147), + listOf(0u, 1u) to Rational(296071, 441), + listOf(1u, 1u) to Rational(-4991281, 882), + listOf(2u, 1u) to Rational(-18702811, 9261), + listOf(3u, 1u) to Rational(40759043, 27783), + listOf(4u, 1u) to Rational(19768501, 27783), + listOf(5u, 1u) to Rational(14307337, 27783), + listOf(6u, 1u) to Rational(1655684, 27783), + listOf(7u, 1u) to Rational(22124, 1323), + listOf(8u, 1u) to Rational(-1504, 441), + listOf(0u, 2u) to Rational(-27667474, 3087), + listOf(1u, 2u) to Rational(265605901, 12348), + listOf(2u, 2u) to Rational(160360775, 98784), + listOf(3u, 2u) to Rational(1169992093, 148176), + listOf(4u, 2u) to Rational(3978014077, 1333584), + listOf(5u, 2u) to Rational(567058123, 333396), + listOf(6u, 2u) to Rational(205132579, 333396), + listOf(7u, 2u) to Rational(566866, 3969), + listOf(8u, 2u) to Rational(41848, 1323), + listOf(0u, 3u) to Rational(-2228822, 1029), + listOf(1u, 3u) to Rational(80179390, 3087), + listOf(2u, 3u) to Rational(-1378630487, 74088), + listOf(3u, 3u) to Rational(-3385811693, 111132), + listOf(4u, 3u) to Rational(-820686977, 49392), + listOf(5u, 3u) to Rational(-89101027, 10584), + listOf(6u, 3u) to Rational(-37847387, 15876), + listOf(7u, 3u) to Rational(-2363369, 3969), + listOf(8u, 3u) to Rational(-108280, 1323), + listOf(0u, 4u) to Rational(12619982, 1029), + listOf(1u, 4u) to Rational(-277723177, 6174), + listOf(2u, 4u) to Rational(649414169, 49392), + listOf(3u, 4u) to Rational(14457595, 63504), + listOf(4u, 4u) to Rational(139270339, 10584), + listOf(5u, 4u) to Rational(140367961, 15876), + listOf(6u, 4u) to Rational(25467083, 7056), + listOf(7u, 4u) to Rational(8563385, 7938), + listOf(8u, 4u) to Rational(19721, 147), + listOf(0u, 5u) to Rational(643850, 147), + listOf(1u, 5u) to Rational(-11818025, 294), + listOf(2u, 5u) to Rational(33963203, 588), + listOf(3u, 5u) to Rational(207216235, 5292), + listOf(4u, 5u) to Rational(2861021, 1512), + listOf(5u, 5u) to Rational(-6302335, 1176), + listOf(6u, 5u) to Rational(-3738587, 882), + listOf(7u, 5u) to Rational(-38437, 27), + listOf(8u, 5u) to Rational(-29620, 189), + listOf(0u, 6u) to Rational(-248725, 49), + listOf(1u, 6u) to Rational(2478535, 98), + listOf(2u, 6u) to Rational(-399721367, 21168), + listOf(3u, 6u) to Rational(-54309317, 10584), + listOf(4u, 6u) to Rational(-95398327, 21168), + listOf(5u, 6u) to Rational(173750, 189), + listOf(6u, 6u) to Rational(92216, 27), + listOf(7u, 6u) to Rational(227744, 189), + listOf(8u, 6u) to Rational(23116, 189), + listOf(0u, 7u) to Rational(-27500, 21), + listOf(1u, 7u) to Rational(120125, 9), + listOf(2u, 7u) to Rational(-279200, 9), + listOf(3u, 7u) to Rational(-100160, 21), + listOf(4u, 7u) to Rational(920452, 63), + listOf(5u, 7u) to Rational(226481, 63), + listOf(6u, 7u) to Rational(-11476, 7), + listOf(7u, 7u) to Rational(-6232, 9), + listOf(8u, 7u) to Rational(-608, 9), + listOf(0u, 8u) to Rational(2500, 3), + listOf(1u, 8u) to Rational(-19000, 3), + listOf(2u, 8u) to Rational(37900, 3), + listOf(3u, 8u) to Rational(-1840, 3), + listOf(4u, 8u) to Rational(-17876, 3), + listOf(5u, 8u) to Rational(-1240, 3), + listOf(6u, 8u) to Rational(2788, 3), + listOf(7u, 8u) to Rational(800, 3), + listOf(8u, 8u) to Rational(64, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + 1 to NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-6, 1), + listOf(1u) to Rational(-9, 8), + listOf(2u) to Rational(17, 5), + listOf(0u, 1u) to Rational(-2, 3), + listOf(1u, 1u) to Rational(1, 5), + listOf(2u, 1u) to Rational(-11, 7), + listOf(0u, 2u) to Rational(13, 6), + listOf(1u, 2u) to Rational(-15, 2), + listOf(2u, 2u) to Rational(-14, 4), + ) + )), + "test 3'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(493, 6), + listOf(1u) to Rational(-15991, 210), + listOf(2u) to Rational(2734, 63), + listOf(3u) to Rational(-8213, 245), + listOf(4u) to Rational(1843, 147), + listOf(5u) to Rational(-432, 245), + listOf(6u) to Rational(4, 49), + listOf(0u, 1u) to Rational(-66, 1), + listOf(1u, 1u) to Rational(-92924, 2205), + listOf(2u, 1u) to Rational(-257461, 2205), + listOf(3u, 1u) to Rational(58658, 2205), + listOf(4u, 1u) to Rational(-87884, 2205), + listOf(5u, 1u) to Rational(2726, 105), + listOf(6u, 1u) to Rational(-52, 21), + listOf(0u, 2u) to Rational(-17569, 147), + listOf(1u, 2u) to Rational(368819, 735), + listOf(2u, 2u) to Rational(-644626, 6615), + listOf(3u, 2u) to Rational(221738, 945), + listOf(4u, 2u) to Rational(-18022, 945), + listOf(5u, 2u) to Rational(-1201, 315), + listOf(6u, 2u) to Rational(1327, 63), + listOf(0u, 3u) to Rational(240, 7), + listOf(1u, 3u) to Rational(-868, 9), + listOf(2u, 3u) to Rational(-8936, 315), + listOf(3u, 3u) to Rational(-77146, 315), + listOf(4u, 3u) to Rational(-4072, 315), + listOf(5u, 3u) to Rational(-2218, 15), + listOf(6u, 3u) to Rational(-104, 3), + listOf(0u, 4u) to Rational(100, 3), + listOf(1u, 4u) to Rational(-725, 3), + listOf(2u, 4u) to Rational(459, 1), + listOf(3u, 4u) to Rational(-2071, 15), + listOf(4u, 4u) to Rational(2831, 15), + listOf(5u, 4u) to Rational(632, 5), + listOf(6u, 4u) to Rational(16, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1255, 9), + listOf(1u) to Rational(-24781, 126), + listOf(2u) to Rational(1195, 14), + listOf(3u) to Rational(-1931, 147), + listOf(4u) to Rational(439, 147), + listOf(5u) to Rational(-172, 343), + listOf(6u) to Rational(4, 147), + listOf(0u, 1u) to Rational(-183, 1), + listOf(1u, 1u) to Rational(-30988, 441), + listOf(2u, 1u) to Rational(-56137, 294), + listOf(3u, 1u) to Rational(204308, 1029), + listOf(4u, 1u) to Rational(-3263, 441), + listOf(5u, 1u) to Rational(2662, 441), + listOf(6u, 1u) to Rational(-52, 63), + listOf(0u, 2u) to Rational(-87119, 294), + listOf(1u, 2u) to Rational(1077919, 686), + listOf(2u, 2u) to Rational(-35209, 147), + listOf(3u, 2u) to Rational(15041, 147), + listOf(4u, 2u) to Rational(240889, 1323), + listOf(5u, 2u) to Rational(27778, 1323), + listOf(6u, 2u) to Rational(1327, 189), + listOf(0u, 3u) to Rational(1620, 7), + listOf(1u, 3u) to Rational(-25716, 49), + listOf(2u, 3u) to Rational(-32078, 49), + listOf(3u, 3u) to Rational(-704038, 441), + listOf(4u, 3u) to Rational(-30190, 63), + listOf(5u, 3u) to Rational(-5414, 63), + listOf(6u, 3u) to Rational(-104, 9), + listOf(0u, 4u) to Rational(225, 1), + listOf(1u, 4u) to Rational(-10560, 7), + listOf(2u, 4u) to Rational(44176, 21), + listOf(3u, 4u) to Rational(28996, 21), + listOf(4u, 4u) to Rational(2405, 7), + listOf(5u, 4u) to Rational(1240, 21), + listOf(6u, 4u) to Rational(16, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 1 to NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(493, 6), + listOf(1u) to Rational(-15991, 210), + listOf(2u) to Rational(2734, 63), + listOf(3u) to Rational(-8213, 245), + listOf(4u) to Rational(1843, 147), + listOf(5u) to Rational(-432, 245), + listOf(6u) to Rational(4, 49), + listOf(0u, 1u) to Rational(-66, 1), + listOf(1u, 1u) to Rational(-92924, 2205), + listOf(2u, 1u) to Rational(-257461, 2205), + listOf(3u, 1u) to Rational(58658, 2205), + listOf(4u, 1u) to Rational(-87884, 2205), + listOf(5u, 1u) to Rational(2726, 105), + listOf(6u, 1u) to Rational(-52, 21), + listOf(0u, 2u) to Rational(-17569, 147), + listOf(1u, 2u) to Rational(368819, 735), + listOf(2u, 2u) to Rational(-644626, 6615), + listOf(3u, 2u) to Rational(221738, 945), + listOf(4u, 2u) to Rational(-18022, 945), + listOf(5u, 2u) to Rational(-1201, 315), + listOf(6u, 2u) to Rational(1327, 63), + listOf(0u, 3u) to Rational(240, 7), + listOf(1u, 3u) to Rational(-868, 9), + listOf(2u, 3u) to Rational(-8936, 315), + listOf(3u, 3u) to Rational(-77146, 315), + listOf(4u, 3u) to Rational(-4072, 315), + listOf(5u, 3u) to Rational(-2218, 15), + listOf(6u, 3u) to Rational(-104, 3), + listOf(0u, 4u) to Rational(100, 3), + listOf(1u, 4u) to Rational(-725, 3), + listOf(2u, 4u) to Rational(459, 1), + listOf(3u, 4u) to Rational(-2071, 15), + listOf(4u, 4u) to Rational(2831, 15), + listOf(5u, 4u) to Rational(632, 5), + listOf(6u, 4u) to Rational(16, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1255, 9), + listOf(1u) to Rational(-24781, 126), + listOf(2u) to Rational(1195, 14), + listOf(3u) to Rational(-1931, 147), + listOf(4u) to Rational(439, 147), + listOf(5u) to Rational(-172, 343), + listOf(6u) to Rational(4, 147), + listOf(0u, 1u) to Rational(-183, 1), + listOf(1u, 1u) to Rational(-30988, 441), + listOf(2u, 1u) to Rational(-56137, 294), + listOf(3u, 1u) to Rational(204308, 1029), + listOf(4u, 1u) to Rational(-3263, 441), + listOf(5u, 1u) to Rational(2662, 441), + listOf(6u, 1u) to Rational(-52, 63), + listOf(0u, 2u) to Rational(-87119, 294), + listOf(1u, 2u) to Rational(1077919, 686), + listOf(2u, 2u) to Rational(-35209, 147), + listOf(3u, 2u) to Rational(15041, 147), + listOf(4u, 2u) to Rational(240889, 1323), + listOf(5u, 2u) to Rational(27778, 1323), + listOf(6u, 2u) to Rational(1327, 189), + listOf(0u, 3u) to Rational(1620, 7), + listOf(1u, 3u) to Rational(-25716, 49), + listOf(2u, 3u) to Rational(-32078, 49), + listOf(3u, 3u) to Rational(-704038, 441), + listOf(4u, 3u) to Rational(-30190, 63), + listOf(5u, 3u) to Rational(-5414, 63), + listOf(6u, 3u) to Rational(-104, 9), + listOf(0u, 4u) to Rational(225, 1), + listOf(1u, 4u) to Rational(-10560, 7), + listOf(2u, 4u) to Rational(44176, 21), + listOf(3u, 4u) to Rational(28996, 21), + listOf(4u, 4u) to Rational(2405, 7), + listOf(5u, 4u) to Rational(1240, 21), + listOf(6u, 4u) to Rational(16, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 1 to NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-6, 1), + listOf(1u) to Rational(-9, 8), + listOf(2u) to Rational(17, 5), + listOf(0u, 1u) to Rational(-2, 3), + listOf(1u, 1u) to Rational(1, 5), + listOf(2u, 1u) to Rational(-11, 7), + listOf(0u, 2u) to Rational(13, 6), + listOf(1u, 2u) to Rational(-15, 2), + listOf(2u, 2u) to Rational(-14, 4), + ) + )), + "test 4'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-409, 6), + listOf(1u) to Rational(-376, 9), + listOf(2u) to Rational(-1781, 81), + listOf(3u) to Rational(-128, 27), + listOf(4u) to Rational(-8, 9), + listOf(0u, 1u) to Rational(18701, 210), + listOf(1u, 1u) to Rational(614183, 7560), + listOf(2u, 1u) to Rational(90941, 1890), + listOf(3u, 1u) to Rational(1802, 135), + listOf(4u, 1u) to Rational(112, 45), + listOf(0u, 2u) to Rational(181421, 315), + listOf(1u, 2u) to Rational(77813, 378), + listOf(2u, 2u) to Rational(598583, 7560), + listOf(3u, 2u) to Rational(85, 27), + listOf(4u, 2u) to Rational(2, 5), + listOf(0u, 3u) to Rational(130997, 315), + listOf(1u, 3u) to Rational(1093, 420), + listOf(2u, 3u) to Rational(9551, 2520), + listOf(3u, 3u) to Rational(-14, 45), + listOf(4u, 3u) to Rational(22, 45), + listOf(0u, 4u) to Rational(-2801, 9), + listOf(1u, 4u) to Rational(4033, 90), + listOf(2u, 4u) to Rational(6429, 80), + listOf(3u, 4u) to Rational(2851, 90), + listOf(4u, 4u) to Rational(293, 45), + listOf(0u, 5u) to Rational(-220, 1), + listOf(1u, 5u) to Rational(127, 1), + listOf(2u, 5u) to Rational(202, 5), + listOf(3u, 5u) to Rational(-63, 5), + listOf(4u, 5u) to Rational(-12, 5), + listOf(0u, 6u) to Rational(100, 1), + listOf(1u, 6u) to Rational(-80, 1), + listOf(2u, 6u) to Rational(-24, 1), + listOf(3u, 6u) to Rational(16, 1), + listOf(4u, 6u) to Rational(4, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(5407, 9), + listOf(1u) to Rational(9568, 27), + listOf(2u) to Rational(4996, 27), + listOf(3u) to Rational(352, 9), + listOf(4u) to Rational(22, 3), + listOf(0u, 1u) to Rational(104411, 126), + listOf(1u, 1u) to Rational(6001, 126), + listOf(2u, 1u) to Rational(-796, 21), + listOf(3u, 1u) to Rational(-5389, 126), + listOf(4u, 1u) to Rational(-166, 21), + listOf(0u, 2u) to Rational(-35327, 126), + listOf(1u, 2u) to Rational(53, 252), + listOf(2u, 2u) to Rational(849197, 6048), + listOf(3u, 2u) to Rational(22361, 252), + listOf(4u, 2u) to Rational(773, 42), + listOf(0u, 3u) to Rational(-6067, 21), + listOf(1u, 3u) to Rational(39049, 126), + listOf(2u, 3u) to Rational(80303, 1008), + listOf(3u, 3u) to Rational(-3035, 63), + listOf(4u, 3u) to Rational(-209, 21), + listOf(0u, 4u) to Rational(3113, 21), + listOf(1u, 4u) to Rational(-22345, 126), + listOf(2u, 4u) to Rational(-30931, 1008), + listOf(3u, 4u) to Rational(5837, 126), + listOf(4u, 4u) to Rational(229, 21), + listOf(0u, 5u) to Rational(-2120, 21), + listOf(1u, 5u) to Rational(451, 7), + listOf(2u, 5u) to Rational(422, 21), + listOf(3u, 5u) to Rational(-181, 21), + listOf(4u, 5u) to Rational(-40, 21), + listOf(0u, 6u) to Rational(100, 3), + listOf(1u, 6u) to Rational(-80, 3), + listOf(2u, 6u) to Rational(-8, 1), + listOf(3u, 6u) to Rational(16, 3), + listOf(4u, 6u) to Rational(4, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-409, 6), + listOf(1u) to Rational(-376, 9), + listOf(2u) to Rational(-1781, 81), + listOf(3u) to Rational(-128, 27), + listOf(4u) to Rational(-8, 9), + listOf(0u, 1u) to Rational(18701, 210), + listOf(1u, 1u) to Rational(614183, 7560), + listOf(2u, 1u) to Rational(90941, 1890), + listOf(3u, 1u) to Rational(1802, 135), + listOf(4u, 1u) to Rational(112, 45), + listOf(0u, 2u) to Rational(181421, 315), + listOf(1u, 2u) to Rational(77813, 378), + listOf(2u, 2u) to Rational(598583, 7560), + listOf(3u, 2u) to Rational(85, 27), + listOf(4u, 2u) to Rational(2, 5), + listOf(0u, 3u) to Rational(130997, 315), + listOf(1u, 3u) to Rational(1093, 420), + listOf(2u, 3u) to Rational(9551, 2520), + listOf(3u, 3u) to Rational(-14, 45), + listOf(4u, 3u) to Rational(22, 45), + listOf(0u, 4u) to Rational(-2801, 9), + listOf(1u, 4u) to Rational(4033, 90), + listOf(2u, 4u) to Rational(6429, 80), + listOf(3u, 4u) to Rational(2851, 90), + listOf(4u, 4u) to Rational(293, 45), + listOf(0u, 5u) to Rational(-220, 1), + listOf(1u, 5u) to Rational(127, 1), + listOf(2u, 5u) to Rational(202, 5), + listOf(3u, 5u) to Rational(-63, 5), + listOf(4u, 5u) to Rational(-12, 5), + listOf(0u, 6u) to Rational(100, 1), + listOf(1u, 6u) to Rational(-80, 1), + listOf(2u, 6u) to Rational(-24, 1), + listOf(3u, 6u) to Rational(16, 1), + listOf(4u, 6u) to Rational(4, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(5407, 9), + listOf(1u) to Rational(9568, 27), + listOf(2u) to Rational(4996, 27), + listOf(3u) to Rational(352, 9), + listOf(4u) to Rational(22, 3), + listOf(0u, 1u) to Rational(104411, 126), + listOf(1u, 1u) to Rational(6001, 126), + listOf(2u, 1u) to Rational(-796, 21), + listOf(3u, 1u) to Rational(-5389, 126), + listOf(4u, 1u) to Rational(-166, 21), + listOf(0u, 2u) to Rational(-35327, 126), + listOf(1u, 2u) to Rational(53, 252), + listOf(2u, 2u) to Rational(849197, 6048), + listOf(3u, 2u) to Rational(22361, 252), + listOf(4u, 2u) to Rational(773, 42), + listOf(0u, 3u) to Rational(-6067, 21), + listOf(1u, 3u) to Rational(39049, 126), + listOf(2u, 3u) to Rational(80303, 1008), + listOf(3u, 3u) to Rational(-3035, 63), + listOf(4u, 3u) to Rational(-209, 21), + listOf(0u, 4u) to Rational(3113, 21), + listOf(1u, 4u) to Rational(-22345, 126), + listOf(2u, 4u) to Rational(-30931, 1008), + listOf(3u, 4u) to Rational(5837, 126), + listOf(4u, 4u) to Rational(229, 21), + listOf(0u, 5u) to Rational(-2120, 21), + listOf(1u, 5u) to Rational(451, 7), + listOf(2u, 5u) to Rational(422, 21), + listOf(3u, 5u) to Rational(-181, 21), + listOf(4u, 5u) to Rational(-40, 21), + listOf(0u, 6u) to Rational(100, 3), + listOf(1u, 6u) to Rational(-80, 3), + listOf(2u, 6u) to Rational(-8, 1), + listOf(3u, 6u) to Rational(16, 3), + listOf(4u, 6u) to Rational(4, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-6, 1), + listOf(1u) to Rational(-9, 8), + listOf(2u) to Rational(17, 5), + listOf(0u, 1u) to Rational(-2, 3), + listOf(1u, 1u) to Rational(1, 5), + listOf(2u, 1u) to Rational(-11, 7), + listOf(0u, 2u) to Rational(13, 6), + listOf(1u, 2u) to Rational(-15, 2), + listOf(2u, 2u) to Rational(-14, 4), + ) + )), + "test 5'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, mapOf( + 5 to NumberedPolynomialAsIs( + listOf() to Rational(-6, 1), + listOf(1u) to Rational(-9, 8), + listOf(2u) to Rational(17, 5), + listOf(0u, 1u) to Rational(-2, 3), + listOf(1u, 1u) to Rational(1, 5), + listOf(2u, 1u) to Rational(-11, 7), + listOf(0u, 2u) to Rational(13, 6), + listOf(1u, 2u) to Rational(-15, 2), + listOf(2u, 2u) to Rational(-14, 4), + ) + )), + "test 6'" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction_Map() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(4u) to Rational(-17166109, 793800), + listOf(3u, 1u) to Rational(-930960143, 5556600), + listOf(2u, 2u) to Rational(-144665109691, 350065800), + listOf(1u, 3u) to Rational(-17232577, 52920), + listOf(0u, 4u) to Rational(-68141, 1323), + ), + NumberedPolynomialAsIs( + listOf(4u) to Rational(-57522533, 14288400), + listOf(3u, 1u) to Rational(-13085162953, 300056400), + listOf(2u, 2u) to Rational(-92093367341, 525098700), + listOf(1u, 3u) to Rational(-1979342797, 6667920), + listOf(0u, 4u) to Rational(-3082727, 21168), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(11, 5), + listOf(0u, 1u) to Rational(8, 4), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(1, 9), + listOf(0u, 1u) to Rational(11, 7), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(-4, 3), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(3, 6), + listOf(0u, 1u) to Rational(12, 8), + ) + ), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-130778291, 76800), + listOf(1u) to Rational(-445270919, 230400), + listOf(2u) to Rational(44578444937, 14515200), + listOf(3u) to Rational(17329402153, 1555200), + listOf(4u) to Rational(89239926809, 2332800), + listOf(5u) to Rational(2808812267, 145152), + listOf(6u) to Rational(-21362661007, 725760), + listOf(7u) to Rational(-258455443, 2016), + listOf(8u) to Rational(-21454693, 96), + listOf(0u, 1u) to Rational(-1002137, 15360), + listOf(1u, 1u) to Rational(-1704849697, 430080), + listOf(2u, 1u) to Rational(-57657676789, 4838400), + listOf(3u, 1u) to Rational(-101331731, 89600), + listOf(4u, 1u) to Rational(5362280079329, 130636800), + listOf(5u, 1u) to Rational(4069896167053, 130636800), + listOf(6u, 1u) to Rational(12011514569, 544320), + listOf(7u, 1u) to Rational(138293195623, 725760), + listOf(8u, 1u) to Rational(6228779419, 48384), + listOf(0u, 2u) to Rational(-32395872823, 8064000), + listOf(1u, 2u) to Rational(-7398505523, 2304000), + listOf(2u, 2u) to Rational(95217051699521, 3048192000), + listOf(3u, 2u) to Rational(198026968812079, 3657830400), + listOf(4u, 2u) to Rational(4291645618499, 228614400), + listOf(5u, 2u) to Rational(-33211690942439, 914457600), + listOf(6u, 2u) to Rational(-637385538163153, 1371686400), + listOf(7u, 2u) to Rational(-138671528276273, 182891520), + listOf(8u, 2u) to Rational(-14566368751, 217728), + listOf(0u, 3u) to Rational(-10538718719, 2016000), + listOf(1u, 3u) to Rational(-1844485375199, 84672000), + listOf(2u, 3u) to Rational(103968665891, 12096000), + listOf(3u, 3u) to Rational(175402107278351, 1828915200), + listOf(4u, 3u) to Rational(8020699588879, 114307200), + listOf(5u, 3u) to Rational(3414841894991, 38102400), + listOf(6u, 3u) to Rational(1848405591611, 4665600), + listOf(7u, 3u) to Rational(39486708738989, 137168640), + listOf(8u, 3u) to Rational(255926289517, 9144576), + listOf(0u, 4u) to Rational(-655379564629, 105840000), + listOf(1u, 4u) to Rational(-208336039441, 127008000), + listOf(2u, 4u) to Rational(40173146771411, 1143072000), + listOf(3u, 4u) to Rational(150473493581239, 2667168000), + listOf(4u, 4u) to Rational(38833783990483, 1143072000), + listOf(5u, 4u) to Rational(-1963676248203053, 4800902400), + listOf(6u, 4u) to Rational(-2598759412825747, 3200601600), + listOf(7u, 4u) to Rational(-192895352019667, 1280240640), + listOf(8u, 4u) to Rational(3737382679, 6858432), + listOf(0u, 5u) to Rational(-16959378721, 1890000), + listOf(1u, 5u) to Rational(-1864802244743, 79380000), + listOf(2u, 5u) to Rational(13449261536489, 666792000), + listOf(3u, 5u) to Rational(215272234137329, 2667168000), + listOf(4u, 5u) to Rational(6040691379277, 83349000), + listOf(5u, 5u) to Rational(153687143525887, 800150400), + listOf(6u, 5u) to Rational(475602854903563, 2400451200), + listOf(7u, 5u) to Rational(27315599358749, 640120320), + listOf(8u, 5u) to Rational(-2630413357, 10668672), + listOf(0u, 6u) to Rational(-6654999511, 2646000), + listOf(1u, 6u) to Rational(-67885252327, 15876000), + listOf(2u, 6u) to Rational(5786776220983, 2667168000), + listOf(3u, 6u) to Rational(60615922629083, 1143072000), + listOf(4u, 6u) to Rational(-34703539637627407, 672126336000), + listOf(5u, 6u) to Rational(-744694192134101, 2240421120), + listOf(6u, 6u) to Rational(-1782470617231, 14817600), + listOf(7u, 6u) to Rational(59123208433, 8890560), + listOf(8u, 6u) to Rational(-141653, 5292), + listOf(0u, 7u) to Rational(-338051969, 441000), + listOf(1u, 7u) to Rational(468850013, 1764000), + listOf(2u, 7u) to Rational(2102343426101, 222264000), + listOf(3u, 7u) to Rational(7836130602007, 1333584000), + listOf(4u, 7u) to Rational(16239111865997, 746807040), + listOf(5u, 7u) to Rational(3824649185383, 88905600), + listOf(6u, 7u) to Rational(56058614459, 3457440), + listOf(7u, 7u) to Rational(-396766339, 493920), + listOf(8u, 7u) to Rational(-165147, 2744), + listOf(0u, 8u) to Rational(-3088619, 58800), + listOf(1u, 8u) to Rational(155343347, 88200), + listOf(2u, 8u) to Rational(100098736469, 7408800), + listOf(3u, 8u) to Rational(109725511381, 7408800), + listOf(4u, 8u) to Rational(-2431199641013, 59270400), + listOf(5u, 8u) to Rational(-102872383249, 3457440), + listOf(6u, 8u) to Rational(1449461309, 576240), + listOf(7u, 8u) to Rational(812775, 1372), + listOf(8u, 8u) to Rational(-16461, 343) + ), + NumberedPolynomialAsIs( + listOf() to Rational(164202773, 230400), + listOf(1u) to Rational(-70345303, 518400), + listOf(2u) to Rational(-4229702731, 4665600), + listOf(3u) to Rational(3262171027, 6998400), + listOf(4u) to Rational(-25423104169, 13996800), + listOf(5u) to Rational(64061869, 349920), + listOf(6u) to Rational(-1655878091, 116640), + listOf(7u) to Rational(-7991441, 648), + listOf(8u) to Rational(-502591, 18), + listOf(0u, 1u) to Rational(-8780429, 3840), + listOf(1u, 1u) to Rational(434272361, 115200), + listOf(2u, 1u) to Rational(429825727, 41472), + listOf(3u, 1u) to Rational(-10066790339, 6998400), + listOf(4u, 1u) to Rational(70022035471, 20995200), + listOf(5u, 1u) to Rational(-32070283493, 1399680), + listOf(6u, 1u) to Rational(-22051101001, 1399680), + listOf(7u, 1u) to Rational(-126493427, 12960), + listOf(8u, 1u) to Rational(3050245, 864), + listOf(0u, 2u) to Rational(-1194654631, 345600), + listOf(1u, 2u) to Rational(-542961452671, 31104000), + listOf(2u, 2u) to Rational(-234000873607, 48988800), + listOf(3u, 2u) to Rational(140520538087, 3628800), + listOf(4u, 2u) to Rational(9215088876563, 130636800), + listOf(5u, 2u) to Rational(27590569647253, 293932800), + listOf(6u, 2u) to Rational(5129057792891, 97977600), + listOf(7u, 2u) to Rational(-106334191, 5103), + listOf(8u, 2u) to Rational(-1024113911, 435456), + listOf(0u, 3u) to Rational(76223843, 6000), + listOf(1u, 3u) to Rational(57425857357, 2592000), + listOf(2u, 3u) to Rational(-2044736497573, 46656000), + listOf(3u, 3u) to Rational(-26155810120031, 293932800), + listOf(4u, 3u) to Rational(-1064419459813, 6998400), + listOf(5u, 3u) to Rational(-753782018389, 4082400), + listOf(6u, 3u) to Rational(-291973360873, 2799360), + listOf(7u, 3u) to Rational(-46372122599, 816480), + listOf(8u, 3u) to Rational(3579859657, 653184), + listOf(0u, 4u) to Rational(-13374241901, 4320000), + listOf(1u, 4u) to Rational(306606499811, 54432000), + listOf(2u, 4u) to Rational(964267124745437, 13716864000), + listOf(3u, 4u) to Rational(21603809415373, 182891520), + listOf(4u, 4u) to Rational(1097860214654027, 6858432000), + listOf(5u, 4u) to Rational(161615254570669, 914457600), + listOf(6u, 4u) to Rational(758415239461, 22861440), + listOf(7u, 4u) to Rational(2585568355471, 274337280), + listOf(8u, 4u) to Rational(-70433747863, 9144576), + listOf(0u, 5u) to Rational(-9582586217, 2520000), + listOf(1u, 5u) to Rational(-19093471394171, 635040000), + listOf(2u, 5u) to Rational(-13010261944411, 381024000), + listOf(3u, 5u) to Rational(-259039825301861, 4572288000), + listOf(4u, 5u) to Rational(-305081119071079, 2286144000), + listOf(5u, 5u) to Rational(-1923114383311, 19595520), + listOf(6u, 5u) to Rational(-14181787253231, 228614400), + listOf(7u, 5u) to Rational(-3959584789, 4354560), + listOf(8u, 5u) to Rational(4691742523, 762048), + listOf(0u, 6u) to Rational(-588323437, 180000), + listOf(1u, 6u) to Rational(5952234691, 52920000), + listOf(2u, 6u) to Rational(21001851056959, 1088640000), + listOf(3u, 6u) to Rational(84668034357563, 2133734400), + listOf(4u, 6u) to Rational(2029754605811557, 25604812800), + listOf(5u, 6u) to Rational(11721216739823, 426746880), + listOf(6u, 6u) to Rational(-8275903187003, 2133734400), + listOf(7u, 6u) to Rational(-4730447299, 2540160), + listOf(8u, 6u) to Rational(-46069985, 21168), + listOf(0u, 7u) to Rational(-75711301, 117600), + listOf(1u, 7u) to Rational(32430417413, 7056000), + listOf(2u, 7u) to Rational(677988533153, 98784000), + listOf(3u, 7u) to Rational(-948417645827, 71124480), + listOf(4u, 7u) to Rational(-11320265215207, 711244800), + listOf(5u, 7u) to Rational(-676438627783, 50803200), + listOf(6u, 7u) to Rational(-7382274253, 1975680), + listOf(7u, 7u) to Rational(6505733, 2205), + listOf(8u, 7u) to Rational(450137, 882), + listOf(0u, 8u) to Rational(-8368253, 78400), + listOf(1u, 8u) to Rational(6833783, 117600), + listOf(2u, 8u) to Rational(4528971133, 5927040), + listOf(3u, 8u) to Rational(146252636617, 29635200), + listOf(4u, 8u) to Rational(8321882556889, 1659571200), + listOf(5u, 8u) to Rational(-4686033011, 1975680), + listOf(6u, 8u) to Rational(-1074445963, 987840), + listOf(7u, 8u) to Rational(-142313, 588), + listOf(8u, 8u) to Rational(-4281, 49) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-130778291, 76800), + listOf(1u) to Rational(-445270919, 230400), + listOf(2u) to Rational(44578444937, 14515200), + listOf(3u) to Rational(17329402153, 1555200), + listOf(4u) to Rational(89239926809, 2332800), + listOf(5u) to Rational(2808812267, 145152), + listOf(6u) to Rational(-21362661007, 725760), + listOf(7u) to Rational(-258455443, 2016), + listOf(8u) to Rational(-21454693, 96), + listOf(0u, 1u) to Rational(-1002137, 15360), + listOf(1u, 1u) to Rational(-1704849697, 430080), + listOf(2u, 1u) to Rational(-57657676789, 4838400), + listOf(3u, 1u) to Rational(-101331731, 89600), + listOf(4u, 1u) to Rational(5362280079329, 130636800), + listOf(5u, 1u) to Rational(4069896167053, 130636800), + listOf(6u, 1u) to Rational(12011514569, 544320), + listOf(7u, 1u) to Rational(138293195623, 725760), + listOf(8u, 1u) to Rational(6228779419, 48384), + listOf(0u, 2u) to Rational(-32395872823, 8064000), + listOf(1u, 2u) to Rational(-7398505523, 2304000), + listOf(2u, 2u) to Rational(95217051699521, 3048192000), + listOf(3u, 2u) to Rational(198026968812079, 3657830400), + listOf(4u, 2u) to Rational(4291645618499, 228614400), + listOf(5u, 2u) to Rational(-33211690942439, 914457600), + listOf(6u, 2u) to Rational(-637385538163153, 1371686400), + listOf(7u, 2u) to Rational(-138671528276273, 182891520), + listOf(8u, 2u) to Rational(-14566368751, 217728), + listOf(0u, 3u) to Rational(-10538718719, 2016000), + listOf(1u, 3u) to Rational(-1844485375199, 84672000), + listOf(2u, 3u) to Rational(103968665891, 12096000), + listOf(3u, 3u) to Rational(175402107278351, 1828915200), + listOf(4u, 3u) to Rational(8020699588879, 114307200), + listOf(5u, 3u) to Rational(3414841894991, 38102400), + listOf(6u, 3u) to Rational(1848405591611, 4665600), + listOf(7u, 3u) to Rational(39486708738989, 137168640), + listOf(8u, 3u) to Rational(255926289517, 9144576), + listOf(0u, 4u) to Rational(-655379564629, 105840000), + listOf(1u, 4u) to Rational(-208336039441, 127008000), + listOf(2u, 4u) to Rational(40173146771411, 1143072000), + listOf(3u, 4u) to Rational(150473493581239, 2667168000), + listOf(4u, 4u) to Rational(38833783990483, 1143072000), + listOf(5u, 4u) to Rational(-1963676248203053, 4800902400), + listOf(6u, 4u) to Rational(-2598759412825747, 3200601600), + listOf(7u, 4u) to Rational(-192895352019667, 1280240640), + listOf(8u, 4u) to Rational(3737382679, 6858432), + listOf(0u, 5u) to Rational(-16959378721, 1890000), + listOf(1u, 5u) to Rational(-1864802244743, 79380000), + listOf(2u, 5u) to Rational(13449261536489, 666792000), + listOf(3u, 5u) to Rational(215272234137329, 2667168000), + listOf(4u, 5u) to Rational(6040691379277, 83349000), + listOf(5u, 5u) to Rational(153687143525887, 800150400), + listOf(6u, 5u) to Rational(475602854903563, 2400451200), + listOf(7u, 5u) to Rational(27315599358749, 640120320), + listOf(8u, 5u) to Rational(-2630413357, 10668672), + listOf(0u, 6u) to Rational(-6654999511, 2646000), + listOf(1u, 6u) to Rational(-67885252327, 15876000), + listOf(2u, 6u) to Rational(5786776220983, 2667168000), + listOf(3u, 6u) to Rational(60615922629083, 1143072000), + listOf(4u, 6u) to Rational(-34703539637627407, 672126336000), + listOf(5u, 6u) to Rational(-744694192134101, 2240421120), + listOf(6u, 6u) to Rational(-1782470617231, 14817600), + listOf(7u, 6u) to Rational(59123208433, 8890560), + listOf(8u, 6u) to Rational(-141653, 5292), + listOf(0u, 7u) to Rational(-338051969, 441000), + listOf(1u, 7u) to Rational(468850013, 1764000), + listOf(2u, 7u) to Rational(2102343426101, 222264000), + listOf(3u, 7u) to Rational(7836130602007, 1333584000), + listOf(4u, 7u) to Rational(16239111865997, 746807040), + listOf(5u, 7u) to Rational(3824649185383, 88905600), + listOf(6u, 7u) to Rational(56058614459, 3457440), + listOf(7u, 7u) to Rational(-396766339, 493920), + listOf(8u, 7u) to Rational(-165147, 2744), + listOf(0u, 8u) to Rational(-3088619, 58800), + listOf(1u, 8u) to Rational(155343347, 88200), + listOf(2u, 8u) to Rational(100098736469, 7408800), + listOf(3u, 8u) to Rational(109725511381, 7408800), + listOf(4u, 8u) to Rational(-2431199641013, 59270400), + listOf(5u, 8u) to Rational(-102872383249, 3457440), + listOf(6u, 8u) to Rational(1449461309, 576240), + listOf(7u, 8u) to Rational(812775, 1372), + listOf(8u, 8u) to Rational(-16461, 343) + ), + NumberedPolynomialAsIs( + listOf() to Rational(164202773, 230400), + listOf(1u) to Rational(-70345303, 518400), + listOf(2u) to Rational(-4229702731, 4665600), + listOf(3u) to Rational(3262171027, 6998400), + listOf(4u) to Rational(-25423104169, 13996800), + listOf(5u) to Rational(64061869, 349920), + listOf(6u) to Rational(-1655878091, 116640), + listOf(7u) to Rational(-7991441, 648), + listOf(8u) to Rational(-502591, 18), + listOf(0u, 1u) to Rational(-8780429, 3840), + listOf(1u, 1u) to Rational(434272361, 115200), + listOf(2u, 1u) to Rational(429825727, 41472), + listOf(3u, 1u) to Rational(-10066790339, 6998400), + listOf(4u, 1u) to Rational(70022035471, 20995200), + listOf(5u, 1u) to Rational(-32070283493, 1399680), + listOf(6u, 1u) to Rational(-22051101001, 1399680), + listOf(7u, 1u) to Rational(-126493427, 12960), + listOf(8u, 1u) to Rational(3050245, 864), + listOf(0u, 2u) to Rational(-1194654631, 345600), + listOf(1u, 2u) to Rational(-542961452671, 31104000), + listOf(2u, 2u) to Rational(-234000873607, 48988800), + listOf(3u, 2u) to Rational(140520538087, 3628800), + listOf(4u, 2u) to Rational(9215088876563, 130636800), + listOf(5u, 2u) to Rational(27590569647253, 293932800), + listOf(6u, 2u) to Rational(5129057792891, 97977600), + listOf(7u, 2u) to Rational(-106334191, 5103), + listOf(8u, 2u) to Rational(-1024113911, 435456), + listOf(0u, 3u) to Rational(76223843, 6000), + listOf(1u, 3u) to Rational(57425857357, 2592000), + listOf(2u, 3u) to Rational(-2044736497573, 46656000), + listOf(3u, 3u) to Rational(-26155810120031, 293932800), + listOf(4u, 3u) to Rational(-1064419459813, 6998400), + listOf(5u, 3u) to Rational(-753782018389, 4082400), + listOf(6u, 3u) to Rational(-291973360873, 2799360), + listOf(7u, 3u) to Rational(-46372122599, 816480), + listOf(8u, 3u) to Rational(3579859657, 653184), + listOf(0u, 4u) to Rational(-13374241901, 4320000), + listOf(1u, 4u) to Rational(306606499811, 54432000), + listOf(2u, 4u) to Rational(964267124745437, 13716864000), + listOf(3u, 4u) to Rational(21603809415373, 182891520), + listOf(4u, 4u) to Rational(1097860214654027, 6858432000), + listOf(5u, 4u) to Rational(161615254570669, 914457600), + listOf(6u, 4u) to Rational(758415239461, 22861440), + listOf(7u, 4u) to Rational(2585568355471, 274337280), + listOf(8u, 4u) to Rational(-70433747863, 9144576), + listOf(0u, 5u) to Rational(-9582586217, 2520000), + listOf(1u, 5u) to Rational(-19093471394171, 635040000), + listOf(2u, 5u) to Rational(-13010261944411, 381024000), + listOf(3u, 5u) to Rational(-259039825301861, 4572288000), + listOf(4u, 5u) to Rational(-305081119071079, 2286144000), + listOf(5u, 5u) to Rational(-1923114383311, 19595520), + listOf(6u, 5u) to Rational(-14181787253231, 228614400), + listOf(7u, 5u) to Rational(-3959584789, 4354560), + listOf(8u, 5u) to Rational(4691742523, 762048), + listOf(0u, 6u) to Rational(-588323437, 180000), + listOf(1u, 6u) to Rational(5952234691, 52920000), + listOf(2u, 6u) to Rational(21001851056959, 1088640000), + listOf(3u, 6u) to Rational(84668034357563, 2133734400), + listOf(4u, 6u) to Rational(2029754605811557, 25604812800), + listOf(5u, 6u) to Rational(11721216739823, 426746880), + listOf(6u, 6u) to Rational(-8275903187003, 2133734400), + listOf(7u, 6u) to Rational(-4730447299, 2540160), + listOf(8u, 6u) to Rational(-46069985, 21168), + listOf(0u, 7u) to Rational(-75711301, 117600), + listOf(1u, 7u) to Rational(32430417413, 7056000), + listOf(2u, 7u) to Rational(677988533153, 98784000), + listOf(3u, 7u) to Rational(-948417645827, 71124480), + listOf(4u, 7u) to Rational(-11320265215207, 711244800), + listOf(5u, 7u) to Rational(-676438627783, 50803200), + listOf(6u, 7u) to Rational(-7382274253, 1975680), + listOf(7u, 7u) to Rational(6505733, 2205), + listOf(8u, 7u) to Rational(450137, 882), + listOf(0u, 8u) to Rational(-8368253, 78400), + listOf(1u, 8u) to Rational(6833783, 117600), + listOf(2u, 8u) to Rational(4528971133, 5927040), + listOf(3u, 8u) to Rational(146252636617, 29635200), + listOf(4u, 8u) to Rational(8321882556889, 1659571200), + listOf(5u, 8u) to Rational(-4686033011, 1975680), + listOf(6u, 8u) to Rational(-1074445963, 987840), + listOf(7u, 8u) to Rational(-142313, 588), + listOf(8u, 8u) to Rational(-4281, 49) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 8), + listOf(1u) to Rational(-12, 6), + listOf(2u) to Rational(7, 6), + listOf(0u, 1u) to Rational(-10, 4), + listOf(1u, 1u) to Rational(-7, 6), + listOf(2u, 1u) to Rational(8, 9), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-13, 4), + listOf(2u, 2u) to Rational(5, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(10, 6), + listOf(1u) to Rational(-18, 6), + listOf(2u) to Rational(5, 1), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(8, 4), + listOf(2u, 1u) to Rational(-4, 9), + listOf(0u, 2u) to Rational(-6, 5), + listOf(1u, 2u) to Rational(-15, 8), + listOf(2u, 2u) to Rational(-18, 5), + ) + ), + )), + "test 3'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(2303, 64), + listOf(1u) to Rational(31843, 192), + listOf(2u) to Rational(118891, 576), + listOf(3u) to Rational(94453, 168), + listOf(4u) to Rational(-179203, 1512), + listOf(5u) to Rational(-16979, 126), + listOf(6u) to Rational(-13499, 12), + listOf(0u, 1u) to Rational(-4767, 64), + listOf(1u, 1u) to Rational(-58689, 256), + listOf(2u, 1u) to Rational(-757333, 4032), + listOf(3u, 1u) to Rational(-4921205, 4032), + listOf(4u, 1u) to Rational(-2930815, 4032), + listOf(5u, 1u) to Rational(-398803, 1512), + listOf(6u, 1u) to Rational(18835, 36), + listOf(0u, 2u) to Rational(224101, 960), + listOf(1u, 2u) to Rational(9139699, 40320), + listOf(2u, 2u) to Rational(3848803, 5760), + listOf(3u, 2u) to Rational(93102371, 241920), + listOf(4u, 2u) to Rational(-65821229, 141120), + listOf(5u, 2u) to Rational(-15675899, 7056), + listOf(6u, 2u) to Rational(10459, 189), + listOf(0u, 3u) to Rational(2411, 16), + listOf(1u, 3u) to Rational(1294543, 10080), + listOf(2u, 3u) to Rational(-1740199, 1440), + listOf(3u, 3u) to Rational(-266994841, 282240), + listOf(4u, 3u) to Rational(-41261893, 211680), + listOf(5u, 3u) to Rational(1717357, 3528), + listOf(6u, 3u) to Rational(69, 14), + listOf(0u, 4u) to Rational(13231, 360), + listOf(1u, 4u) to Rational(4858831, 25200), + listOf(2u, 4u) to Rational(15565759, 75600), + listOf(3u, 4u) to Rational(-15583391, 35280), + listOf(4u, 4u) to Rational(-13345747, 11760), + listOf(5u, 4u) to Rational(140103, 686), + listOf(6u, 4u) to Rational(-765, 49) + ), + NumberedPolynomialAsIs( + listOf() to Rational(31409, 576), + listOf(1u) to Rational(-337099, 1728), + listOf(2u) to Rational(-211429, 1728), + listOf(3u) to Rational(-259241, 432), + listOf(4u) to Rational(-13777, 36), + listOf(5u) to Rational(-41389, 72), + listOf(6u) to Rational(-7679, 48), + listOf(0u, 1u) to Rational(-3269, 12), + listOf(1u, 1u) to Rational(629569, 864), + listOf(2u, 1u) to Rational(53867, 324), + listOf(3u, 1u) to Rational(2290577, 1728), + listOf(4u, 1u) to Rational(101507, 216), + listOf(5u, 1u) to Rational(213109, 288), + listOf(6u, 1u) to Rational(17927, 144), + listOf(0u, 2u) to Rational(314587, 1080), + listOf(1u, 2u) to Rational(-109771, 144), + listOf(2u, 2u) to Rational(-6469, 16), + listOf(3u, 2u) to Rational(-298291681, 181440), + listOf(4u, 2u) to Rational(-59147357, 48384), + listOf(5u, 2u) to Rational(-4982365, 6048), + listOf(6u, 2u) to Rational(-18727, 576), + listOf(0u, 3u) to Rational(12379, 90), + listOf(1u, 3u) to Rational(-542911, 1620), + listOf(2u, 3u) to Rational(143123, 1260), + listOf(3u, 3u) to Rational(9859177, 30240), + listOf(4u, 3u) to Rational(9312529, 20160), + listOf(5u, 3u) to Rational(207001, 672), + listOf(6u, 3u) to Rational(203, 24), + listOf(0u, 4u) to Rational(9442, 675), + listOf(1u, 4u) to Rational(-13729, 300), + listOf(2u, 4u) to Rational(-3490471, 25200), + listOf(3u, 4u) to Rational(-333031, 840), + listOf(4u, 4u) to Rational(-7572211, 47040), + listOf(5u, 4u) to Rational(-1189, 56), + listOf(6u, 4u) to Rational(-405, 196) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(2303, 64), + listOf(1u) to Rational(31843, 192), + listOf(2u) to Rational(118891, 576), + listOf(3u) to Rational(94453, 168), + listOf(4u) to Rational(-179203, 1512), + listOf(5u) to Rational(-16979, 126), + listOf(6u) to Rational(-13499, 12), + listOf(0u, 1u) to Rational(-4767, 64), + listOf(1u, 1u) to Rational(-58689, 256), + listOf(2u, 1u) to Rational(-757333, 4032), + listOf(3u, 1u) to Rational(-4921205, 4032), + listOf(4u, 1u) to Rational(-2930815, 4032), + listOf(5u, 1u) to Rational(-398803, 1512), + listOf(6u, 1u) to Rational(18835, 36), + listOf(0u, 2u) to Rational(224101, 960), + listOf(1u, 2u) to Rational(9139699, 40320), + listOf(2u, 2u) to Rational(3848803, 5760), + listOf(3u, 2u) to Rational(93102371, 241920), + listOf(4u, 2u) to Rational(-65821229, 141120), + listOf(5u, 2u) to Rational(-15675899, 7056), + listOf(6u, 2u) to Rational(10459, 189), + listOf(0u, 3u) to Rational(2411, 16), + listOf(1u, 3u) to Rational(1294543, 10080), + listOf(2u, 3u) to Rational(-1740199, 1440), + listOf(3u, 3u) to Rational(-266994841, 282240), + listOf(4u, 3u) to Rational(-41261893, 211680), + listOf(5u, 3u) to Rational(1717357, 3528), + listOf(6u, 3u) to Rational(69, 14), + listOf(0u, 4u) to Rational(13231, 360), + listOf(1u, 4u) to Rational(4858831, 25200), + listOf(2u, 4u) to Rational(15565759, 75600), + listOf(3u, 4u) to Rational(-15583391, 35280), + listOf(4u, 4u) to Rational(-13345747, 11760), + listOf(5u, 4u) to Rational(140103, 686), + listOf(6u, 4u) to Rational(-765, 49) + ), + NumberedPolynomialAsIs( + listOf() to Rational(31409, 576), + listOf(1u) to Rational(-337099, 1728), + listOf(2u) to Rational(-211429, 1728), + listOf(3u) to Rational(-259241, 432), + listOf(4u) to Rational(-13777, 36), + listOf(5u) to Rational(-41389, 72), + listOf(6u) to Rational(-7679, 48), + listOf(0u, 1u) to Rational(-3269, 12), + listOf(1u, 1u) to Rational(629569, 864), + listOf(2u, 1u) to Rational(53867, 324), + listOf(3u, 1u) to Rational(2290577, 1728), + listOf(4u, 1u) to Rational(101507, 216), + listOf(5u, 1u) to Rational(213109, 288), + listOf(6u, 1u) to Rational(17927, 144), + listOf(0u, 2u) to Rational(314587, 1080), + listOf(1u, 2u) to Rational(-109771, 144), + listOf(2u, 2u) to Rational(-6469, 16), + listOf(3u, 2u) to Rational(-298291681, 181440), + listOf(4u, 2u) to Rational(-59147357, 48384), + listOf(5u, 2u) to Rational(-4982365, 6048), + listOf(6u, 2u) to Rational(-18727, 576), + listOf(0u, 3u) to Rational(12379, 90), + listOf(1u, 3u) to Rational(-542911, 1620), + listOf(2u, 3u) to Rational(143123, 1260), + listOf(3u, 3u) to Rational(9859177, 30240), + listOf(4u, 3u) to Rational(9312529, 20160), + listOf(5u, 3u) to Rational(207001, 672), + listOf(6u, 3u) to Rational(203, 24), + listOf(0u, 4u) to Rational(9442, 675), + listOf(1u, 4u) to Rational(-13729, 300), + listOf(2u, 4u) to Rational(-3490471, 25200), + listOf(3u, 4u) to Rational(-333031, 840), + listOf(4u, 4u) to Rational(-7572211, 47040), + listOf(5u, 4u) to Rational(-1189, 56), + listOf(6u, 4u) to Rational(-405, 196) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 1 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 8), + listOf(1u) to Rational(-12, 6), + listOf(2u) to Rational(7, 6), + listOf(0u, 1u) to Rational(-10, 4), + listOf(1u, 1u) to Rational(-7, 6), + listOf(2u, 1u) to Rational(8, 9), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-13, 4), + listOf(2u, 2u) to Rational(5, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(10, 6), + listOf(1u) to Rational(-18, 6), + listOf(2u) to Rational(5, 1), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(8, 4), + listOf(2u, 1u) to Rational(-4, 9), + listOf(0u, 2u) to Rational(-6, 5), + listOf(1u, 2u) to Rational(-15, 8), + listOf(2u, 2u) to Rational(-18, 5), + ) + ), + )), + "test 4'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-506213, 2800), + listOf(1u) to Rational(9859, 315), + listOf(2u) to Rational(17384377, 11340), + listOf(3u) to Rational(-9662, 63), + listOf(4u) to Rational(-12563, 4), + listOf(0u, 1u) to Rational(-486293, 22400), + listOf(1u, 1u) to Rational(-6530947, 25200), + listOf(2u, 1u) to Rational(866125, 18144), + listOf(3u, 1u) to Rational(2948747, 2520), + listOf(4u, 1u) to Rational(1196611, 2016), + listOf(0u, 2u) to Rational(-20266021, 117600), + listOf(1u, 2u) to Rational(26656339, 44100), + listOf(2u, 2u) to Rational(19499183, 18144), + listOf(3u, 2u) to Rational(-19801849, 7560), + listOf(4u, 2u) to Rational(-2639635, 1296), + listOf(0u, 3u) to Rational(-5017697, 29400), + listOf(1u, 3u) to Rational(-606007, 1575), + listOf(2u, 3u) to Rational(127494487, 132300), + listOf(3u, 3u) to Rational(166567, 105), + listOf(4u, 3u) to Rational(486403, 18144), + listOf(0u, 4u) to Rational(-32182, 735), + listOf(1u, 4u) to Rational(2420671, 8820), + listOf(2u, 4u) to Rational(-12619193, 26460), + listOf(3u, 4u) to Rational(-6823067, 5670), + listOf(4u, 4u) to Rational(-2311693, 13608), + listOf(0u, 5u) to Rational(-13324, 245), + listOf(1u, 5u) to Rational(1966, 35), + listOf(2u, 5u) to Rational(1052719, 2520), + listOf(3u, 5u) to Rational(19153, 270), + listOf(4u, 5u) to Rational(701, 54), + listOf(0u, 6u) to Rational(4647, 196), + listOf(1u, 6u) to Rational(2197, 28), + listOf(2u, 6u) to Rational(-43853, 336), + listOf(3u, 6u) to Rational(-301, 3), + listOf(4u, 6u) to Rational(34, 3) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2843, 1600), + listOf(1u) to Rational(-1483, 240), + listOf(2u) to Rational(110623, 1296), + listOf(3u) to Rational(1265, 72), + listOf(4u) to Rational(-5011, 16), + listOf(0u, 1u) to Rational(47743, 1800), + listOf(1u, 1u) to Rational(619229, 32400), + listOf(2u, 1u) to Rational(-5978369, 58320), + listOf(3u, 1u) to Rational(-86081, 1620), + listOf(4u, 1u) to Rational(6325, 72), + listOf(0u, 2u) to Rational(110951, 3360), + listOf(1u, 2u) to Rational(-9550649, 302400), + listOf(2u, 2u) to Rational(6542933, 85050), + listOf(3u, 2u) to Rational(4708291, 38880), + listOf(4u, 2u) to Rational(-433327, 1296), + listOf(0u, 3u) to Rational(56143, 600), + listOf(1u, 3u) to Rational(94243, 720), + listOf(2u, 3u) to Rational(-46779139, 226800), + listOf(3u, 3u) to Rational(-6948253, 12960), + listOf(4u, 3u) to Rational(-260261, 486), + listOf(0u, 4u) to Rational(-3205317, 19600), + listOf(1u, 4u) to Rational(-201253, 1050), + listOf(2u, 4u) to Rational(332192677, 302400), + listOf(3u, 4u) to Rational(351511, 360), + listOf(4u, 4u) to Rational(-40547, 81), + listOf(0u, 5u) to Rational(-65421, 1960), + listOf(1u, 5u) to Rational(-10118, 35), + listOf(2u, 5u) to Rational(-4341709, 10080), + listOf(3u, 5u) to Rational(-91703, 360), + listOf(4u, 5u) to Rational(-85, 9), + listOf(0u, 6u) to Rational(-25965, 784), + listOf(1u, 6u) to Rational(3351, 16), + listOf(2u, 6u) to Rational(595159, 1344), + listOf(3u, 6u) to Rational(-1381, 12), + listOf(4u, 6u) to Rational(-155, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-506213, 2800), + listOf(1u) to Rational(9859, 315), + listOf(2u) to Rational(17384377, 11340), + listOf(3u) to Rational(-9662, 63), + listOf(4u) to Rational(-12563, 4), + listOf(0u, 1u) to Rational(-486293, 22400), + listOf(1u, 1u) to Rational(-6530947, 25200), + listOf(2u, 1u) to Rational(866125, 18144), + listOf(3u, 1u) to Rational(2948747, 2520), + listOf(4u, 1u) to Rational(1196611, 2016), + listOf(0u, 2u) to Rational(-20266021, 117600), + listOf(1u, 2u) to Rational(26656339, 44100), + listOf(2u, 2u) to Rational(19499183, 18144), + listOf(3u, 2u) to Rational(-19801849, 7560), + listOf(4u, 2u) to Rational(-2639635, 1296), + listOf(0u, 3u) to Rational(-5017697, 29400), + listOf(1u, 3u) to Rational(-606007, 1575), + listOf(2u, 3u) to Rational(127494487, 132300), + listOf(3u, 3u) to Rational(166567, 105), + listOf(4u, 3u) to Rational(486403, 18144), + listOf(0u, 4u) to Rational(-32182, 735), + listOf(1u, 4u) to Rational(2420671, 8820), + listOf(2u, 4u) to Rational(-12619193, 26460), + listOf(3u, 4u) to Rational(-6823067, 5670), + listOf(4u, 4u) to Rational(-2311693, 13608), + listOf(0u, 5u) to Rational(-13324, 245), + listOf(1u, 5u) to Rational(1966, 35), + listOf(2u, 5u) to Rational(1052719, 2520), + listOf(3u, 5u) to Rational(19153, 270), + listOf(4u, 5u) to Rational(701, 54), + listOf(0u, 6u) to Rational(4647, 196), + listOf(1u, 6u) to Rational(2197, 28), + listOf(2u, 6u) to Rational(-43853, 336), + listOf(3u, 6u) to Rational(-301, 3), + listOf(4u, 6u) to Rational(34, 3) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2843, 1600), + listOf(1u) to Rational(-1483, 240), + listOf(2u) to Rational(110623, 1296), + listOf(3u) to Rational(1265, 72), + listOf(4u) to Rational(-5011, 16), + listOf(0u, 1u) to Rational(47743, 1800), + listOf(1u, 1u) to Rational(619229, 32400), + listOf(2u, 1u) to Rational(-5978369, 58320), + listOf(3u, 1u) to Rational(-86081, 1620), + listOf(4u, 1u) to Rational(6325, 72), + listOf(0u, 2u) to Rational(110951, 3360), + listOf(1u, 2u) to Rational(-9550649, 302400), + listOf(2u, 2u) to Rational(6542933, 85050), + listOf(3u, 2u) to Rational(4708291, 38880), + listOf(4u, 2u) to Rational(-433327, 1296), + listOf(0u, 3u) to Rational(56143, 600), + listOf(1u, 3u) to Rational(94243, 720), + listOf(2u, 3u) to Rational(-46779139, 226800), + listOf(3u, 3u) to Rational(-6948253, 12960), + listOf(4u, 3u) to Rational(-260261, 486), + listOf(0u, 4u) to Rational(-3205317, 19600), + listOf(1u, 4u) to Rational(-201253, 1050), + listOf(2u, 4u) to Rational(332192677, 302400), + listOf(3u, 4u) to Rational(351511, 360), + listOf(4u, 4u) to Rational(-40547, 81), + listOf(0u, 5u) to Rational(-65421, 1960), + listOf(1u, 5u) to Rational(-10118, 35), + listOf(2u, 5u) to Rational(-4341709, 10080), + listOf(3u, 5u) to Rational(-91703, 360), + listOf(4u, 5u) to Rational(-85, 9), + listOf(0u, 6u) to Rational(-25965, 784), + listOf(1u, 6u) to Rational(3351, 16), + listOf(2u, 6u) to Rational(595159, 1344), + listOf(3u, 6u) to Rational(-1381, 12), + listOf(4u, 6u) to Rational(-155, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 0 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 8), + listOf(1u) to Rational(-12, 6), + listOf(2u) to Rational(7, 6), + listOf(0u, 1u) to Rational(-10, 4), + listOf(1u, 1u) to Rational(-7, 6), + listOf(2u, 1u) to Rational(8, 9), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-13, 4), + listOf(2u, 2u) to Rational(5, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(10, 6), + listOf(1u) to Rational(-18, 6), + listOf(2u) to Rational(5, 1), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(8, 4), + listOf(2u, 1u) to Rational(-4, 9), + listOf(0u, 2u) to Rational(-6, 5), + listOf(1u, 2u) to Rational(-15, 8), + listOf(2u, 2u) to Rational(-18, 5), + ) + ), + )), + "test 5'" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf>()), + "test 6" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, mapOf( + 5 to NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 8), + listOf(1u) to Rational(-12, 6), + listOf(2u) to Rational(7, 6), + listOf(0u, 1u) to Rational(-10, 4), + listOf(1u, 1u) to Rational(-7, 6), + listOf(2u, 1u) to Rational(8, 9), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-13, 4), + listOf(2u, 2u) to Rational(5, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(10, 6), + listOf(1u) to Rational(-18, 6), + listOf(2u) to Rational(5, 1), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(8, 4), + listOf(2u, 1u) to Rational(-4, 9), + listOf(0u, 2u) to Rational(-6, 5), + listOf(1u, 2u) to Rational(-15, 8), + listOf(2u, 2u) to Rational(-18, 5), + ) + ), + )), + "test 6'" + ) + } + @Test + fun test_Polynomial_substitute_Double_Buffer() { + assertEquals( + NumberedPolynomialAsIs(emptyList() to 0.0), + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ).substitute(bufferOf( + 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf()), + 0.001, + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(0u, 1u) to 0.4561746111587508, + listOf(0u, 2u) to 0.2700930201481795, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf( + 0.0, + )), + 0.001, + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.047895694399743, + listOf(0u, 1u) to 0.859913883275481, + listOf(0u, 2u) to 0.2327806735363575, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf( + 0.4846192734143442, + )), + 0.001, + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.934530767358133, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + )), + 0.001, + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.934530767358133, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + 0.9211194782050933 + )), + 0.001, + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to 1.934530767358133, + ), + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substitute(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + 0.9211194782050933, + 0.4752854632152105 + )), + 0.001, + "test 7" + ) + } + @Test + fun test_Polynomial_substitute_Constant_Buffer() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, bufferOf( + Rational(1) + )), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf()), + "test 2" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-83, 50), + listOf(0u, 1u) to Rational(29, 25), + listOf(0u, 2u) to Rational(3, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + Rational(-2, 5), + )), + "test 3" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5%2C+y+%3D+12%2F9 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(143, 150) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + )), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(143, 150) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + Rational(57, 179), + )), + "test 5" + ) + // https://www.wolframalpha.com/input?i=%28%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2%29+p%5E8+where+x+%3D+q%2Fp%2C+y+%3D+x%5E3%2C+p+%3D+-2%2F5%2C+q+%3D+12%2F9 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(47639065216, 2562890625) + ), + NumberedPolynomialAsIs( + listOf(8u) to Rational(-3, 2), + listOf(7u, 1u) to Rational(8, 6), + listOf(6u, 2u) to Rational(14, 6), + listOf(5u, 3u) to Rational(-3, 1), + listOf(4u, 4u) to Rational(-19, 2), + listOf(3u, 5u) to Rational(9, 4), + listOf(2u, 6u) to Rational(5, 5), + listOf(1u, 7u) to Rational(18, 9), + listOf(0u, 8u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + )), + "test 6" + ) + } + @Test + fun test_Polynomial_substitute_Polynomial_Buffer() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + )), + "test 1" + ) + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-5%2F1+s+%2B+2%2F8+t%2C+y+%3D+11%2F7+t + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(0u, 1u) to Rational(-92, 21), + listOf(0u, 2u) to Rational(-2627, 2352), + listOf(0u, 3u) to Rational(4565, 3136), + listOf(0u, 4u) to Rational(605, 1568), + listOf(1u) to Rational(-20, 3), + listOf(1u, 1u) to Rational(1445, 21), + listOf(1u, 2u) to Rational(-13145, 392), + listOf(1u, 3u) to Rational(-3025, 196), + listOf(2u) to Rational(175, 3), + listOf(2u, 1u) to Rational(2475, 28), + listOf(2u, 2u) to Rational(15125, 98), + listOf(3u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf(1u) to Rational(-5, 1), + listOf(0u, 1u) to Rational(2, 8), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(0, 5), + listOf(0u, 1u) to Rational(11, 7), + ), + )), + "test 2" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = (-9/2 + 2/7 s + 9/1 s^2) + (13/1 + -1/8 s + 2/8 s^2) t + (19/4 + 15/7 s + -19/4 s^2) t^2 + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(48583, 336), + listOf(2u) to Rational(-913477, 1568), + listOf(3u) to Rational(-967567, 672), + listOf(4u) to Rational(4722043, 1344), + listOf(5u) to Rational(8855, 2), + listOf(6u) to Rational(-311971, 32), + listOf(7u) to Rational(-17325, 4), + listOf(8u) to Rational(19845, 2), + listOf(0u, 1u) to Rational(-827, 4), + listOf(1u, 1u) to Rational(191927, 840), + listOf(2u, 1u) to Rational(9592627, 2352), + listOf(3u, 1u) to Rational(-105400711, 53760), + listOf(4u, 1u) to Rational(-10054101459, 439040), + listOf(5u, 1u) to Rational(2127351, 128), + listOf(6u, 1u) to Rational(116680973, 3136), + listOf(7u, 1u) to Rational(-220445, 7), + listOf(8u, 1u) to Rational(-2655, 4), + listOf(0u, 2u) to Rational(30567, 100), + listOf(1u, 2u) to Rational(-156284953, 39200), + listOf(2u, 2u) to Rational(-57661541711, 6585600), + listOf(3u, 2u) to Rational(131931579, 3136), + listOf(4u, 2u) to Rational(98818124791, 3512320), + listOf(5u, 2u) to Rational(-94458855053, 878080), + listOf(6u, 2u) to Rational(13937705305, 1229312), + listOf(7u, 2u) to Rational(335706887, 21952), + listOf(8u, 2u) to Rational(23549165, 1568), + listOf(0u, 3u) to Rational(111367, 1400), + listOf(1u, 3u) to Rational(4937369, 700), + listOf(2u, 3u) to Rational(-4449423711, 274400), + listOf(3u, 3u) to Rational(-351873325703, 4390400), + listOf(4u, 3u) to Rational(23495875029, 307328), + listOf(5u, 3u) to Rational(17576300919, 878080), + listOf(6u, 3u) to Rational(230316993, 12544), + listOf(7u, 3u) to Rational(-191130515, 21952), + listOf(8u, 3u) to Rational(332435, 392), + listOf(0u, 4u) to Rational(-275084, 1225), + listOf(1u, 4u) to Rational(-266774603, 137200), + listOf(2u, 4u) to Rational(2176279167121, 30732800), + listOf(3u, 4u) to Rational(10904913303, 2195200), + listOf(4u, 4u) to Rational(-10769286147, 2195200), + listOf(5u, 4u) to Rational(-26277119793, 439040), + listOf(6u, 4u) to Rational(25859735869, 6146560), + listOf(7u, 4u) to Rational(38906289, 2744), + listOf(8u, 4u) to Rational(-3072025, 392), + listOf(0u, 5u) to Rational(9573, 98), + listOf(1u, 5u) to Rational(-4154651399, 548800), + listOf(2u, 5u) to Rational(3446069019, 548800), + listOf(3u, 5u) to Rational(-7851500623, 137200), + listOf(4u, 5u) to Rational(-53205142903, 1920800), + listOf(5u, 5u) to Rational(-31953611, 3430), + listOf(6u, 5u) to Rational(1447380313, 109760), + listOf(7u, 5u) to Rational(764158625, 21952), + listOf(8u, 5u) to Rational(1153515, 784), + listOf(0u, 6u) to Rational(1722351, 7840), + listOf(1u, 6u) to Rational(-164554821, 109760), + listOf(2u, 6u) to Rational(-79096147243, 7683200), + listOf(3u, 6u) to Rational(-624721089, 15680), + listOf(4u, 6u) to Rational(11147305567, 548800), + listOf(5u, 6u) to Rational(8318333679, 109760), + listOf(6u, 6u) to Rational(32981871553, 1536640), + listOf(7u, 6u) to Rational(-225359619, 21952), + listOf(8u, 6u) to Rational(-3973995, 392), + listOf(0u, 7u) to Rational(67203, 784), + listOf(1u, 7u) to Rational(39281469, 54880), + listOf(2u, 7u) to Rational(70162551, 27440), + listOf(3u, 7u) to Rational(413630709, 54880), + listOf(4u, 7u) to Rational(4640410269, 192080), + listOf(5u, 7u) to Rational(802712247, 54880), + listOf(6u, 7u) to Rational(-473517603, 27440), + listOf(7u, 7u) to Rational(-17055459, 1568), + listOf(8u, 7u) to Rational(-12825, 14), + listOf(0u, 8u) to Rational(16245, 1568), + listOf(1u, 8u) to Rational(503253, 2744), + listOf(2u, 8u) to Rational(125292591, 96040), + listOf(3u, 8u) to Rational(12033171, 2744), + listOf(4u, 8u) to Rational(154352673, 27440), + listOf(5u, 8u) to Rational(-1302291, 392), + listOf(6u, 8u) to Rational(-20265741, 1960), + listOf(7u, 8u) to Rational(-26163, 56), + listOf(8u, 8u) to Rational(146205, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 3), + listOf(1u) to Rational(5, 2), + listOf(2u) to Rational(13, 7), + listOf(0u, 1u) to Rational(16, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(6, 1), + listOf(0u, 2u) to Rational(-14, 3), + listOf(1u, 2u) to Rational(-2, 7), + listOf(2u, 2u) to Rational(-10, 8), + ) + )), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(129, 4), + listOf(1u) to Rational(48583, 336), + listOf(2u) to Rational(-913477, 1568), + listOf(3u) to Rational(-967567, 672), + listOf(4u) to Rational(4722043, 1344), + listOf(5u) to Rational(8855, 2), + listOf(6u) to Rational(-311971, 32), + listOf(7u) to Rational(-17325, 4), + listOf(8u) to Rational(19845, 2), + listOf(0u, 1u) to Rational(-827, 4), + listOf(1u, 1u) to Rational(191927, 840), + listOf(2u, 1u) to Rational(9592627, 2352), + listOf(3u, 1u) to Rational(-105400711, 53760), + listOf(4u, 1u) to Rational(-10054101459, 439040), + listOf(5u, 1u) to Rational(2127351, 128), + listOf(6u, 1u) to Rational(116680973, 3136), + listOf(7u, 1u) to Rational(-220445, 7), + listOf(8u, 1u) to Rational(-2655, 4), + listOf(0u, 2u) to Rational(30567, 100), + listOf(1u, 2u) to Rational(-156284953, 39200), + listOf(2u, 2u) to Rational(-57661541711, 6585600), + listOf(3u, 2u) to Rational(131931579, 3136), + listOf(4u, 2u) to Rational(98818124791, 3512320), + listOf(5u, 2u) to Rational(-94458855053, 878080), + listOf(6u, 2u) to Rational(13937705305, 1229312), + listOf(7u, 2u) to Rational(335706887, 21952), + listOf(8u, 2u) to Rational(23549165, 1568), + listOf(0u, 3u) to Rational(111367, 1400), + listOf(1u, 3u) to Rational(4937369, 700), + listOf(2u, 3u) to Rational(-4449423711, 274400), + listOf(3u, 3u) to Rational(-351873325703, 4390400), + listOf(4u, 3u) to Rational(23495875029, 307328), + listOf(5u, 3u) to Rational(17576300919, 878080), + listOf(6u, 3u) to Rational(230316993, 12544), + listOf(7u, 3u) to Rational(-191130515, 21952), + listOf(8u, 3u) to Rational(332435, 392), + listOf(0u, 4u) to Rational(-275084, 1225), + listOf(1u, 4u) to Rational(-266774603, 137200), + listOf(2u, 4u) to Rational(2176279167121, 30732800), + listOf(3u, 4u) to Rational(10904913303, 2195200), + listOf(4u, 4u) to Rational(-10769286147, 2195200), + listOf(5u, 4u) to Rational(-26277119793, 439040), + listOf(6u, 4u) to Rational(25859735869, 6146560), + listOf(7u, 4u) to Rational(38906289, 2744), + listOf(8u, 4u) to Rational(-3072025, 392), + listOf(0u, 5u) to Rational(9573, 98), + listOf(1u, 5u) to Rational(-4154651399, 548800), + listOf(2u, 5u) to Rational(3446069019, 548800), + listOf(3u, 5u) to Rational(-7851500623, 137200), + listOf(4u, 5u) to Rational(-53205142903, 1920800), + listOf(5u, 5u) to Rational(-31953611, 3430), + listOf(6u, 5u) to Rational(1447380313, 109760), + listOf(7u, 5u) to Rational(764158625, 21952), + listOf(8u, 5u) to Rational(1153515, 784), + listOf(0u, 6u) to Rational(1722351, 7840), + listOf(1u, 6u) to Rational(-164554821, 109760), + listOf(2u, 6u) to Rational(-79096147243, 7683200), + listOf(3u, 6u) to Rational(-624721089, 15680), + listOf(4u, 6u) to Rational(11147305567, 548800), + listOf(5u, 6u) to Rational(8318333679, 109760), + listOf(6u, 6u) to Rational(32981871553, 1536640), + listOf(7u, 6u) to Rational(-225359619, 21952), + listOf(8u, 6u) to Rational(-3973995, 392), + listOf(0u, 7u) to Rational(67203, 784), + listOf(1u, 7u) to Rational(39281469, 54880), + listOf(2u, 7u) to Rational(70162551, 27440), + listOf(3u, 7u) to Rational(413630709, 54880), + listOf(4u, 7u) to Rational(4640410269, 192080), + listOf(5u, 7u) to Rational(802712247, 54880), + listOf(6u, 7u) to Rational(-473517603, 27440), + listOf(7u, 7u) to Rational(-17055459, 1568), + listOf(8u, 7u) to Rational(-12825, 14), + listOf(0u, 8u) to Rational(16245, 1568), + listOf(1u, 8u) to Rational(503253, 2744), + listOf(2u, 8u) to Rational(125292591, 96040), + listOf(3u, 8u) to Rational(12033171, 2744), + listOf(4u, 8u) to Rational(154352673, 27440), + listOf(5u, 8u) to Rational(-1302291, 392), + listOf(6u, 8u) to Rational(-20265741, 1960), + listOf(7u, 8u) to Rational(-26163, 56), + listOf(8u, 8u) to Rational(146205, 32), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-9, 2), + listOf(1u) to Rational(2, 7), + listOf(2u) to Rational(9, 1), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-1, 8), + listOf(2u, 1u) to Rational(2, 8), + listOf(0u, 2u) to Rational(19, 4), + listOf(1u, 2u) to Rational(15, 7), + listOf(2u, 2u) to Rational(-19, 4), + ), + )), + "test 4" + ) + // (-3/2 + 8/6 x + 14/6 x^2) + (-3/1 + -19/2 x + 9/4 x^2) y + (5/5 + 18/9 x + 5/2 x^2) y^2 where x = (0/6 + 14/8 s + -14/2 s^2) + (-3/5 + 11/1 s + 3/7 s^2) t + (-3/7 + -18/5 s + -9/1 s^2) t^2, y = t + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(7, 3), + listOf(2u) to Rational(-35, 16), + listOf(3u) to Rational(-343, 6), + listOf(4u) to Rational(343, 3), + listOf(0u, 1u) to Rational(-19, 5), + listOf(1u, 1u) to Rational(-823, 120), + listOf(2u, 1u) to Rational(1232417, 6720), + listOf(3u, 1u) to Rational(-9863, 24), + listOf(4u, 1u) to Rational(385, 4), + listOf(0u, 2u) to Rational(2439, 350), + listOf(1u, 2u) to Rational(-5793, 40), + listOf(2u, 2u) to Rational(1172113, 3360), + listOf(3u, 2u) to Rational(-13531, 40), + listOf(4u, 2u) to Rational(2824, 7), + listOf(0u, 3u) to Rational(3417, 700), + listOf(1u, 3u) to Rational(1191, 200), + listOf(2u, 3u) to Rational(8383, 28), + listOf(3u, 3u) to Rational(-220279, 280), + listOf(4u, 3u) to Rational(49179, 196), + listOf(0u, 4u) to Rational(57, 35), + listOf(1u, 4u) to Rational(-33771, 700), + listOf(2u, 4u) to Rational(196279, 1225), + listOf(3u, 4u) to Rational(-32259, 140), + listOf(4u, 4u) to Rational(23868, 49), + listOf(0u, 5u) to Rational(333, 196), + listOf(1u, 5u) to Rational(-204, 35), + listOf(2u, 5u) to Rational(-307233, 2450), + listOf(3u, 5u) to Rational(-12492, 35), + listOf(4u, 5u) to Rational(4563, 28), + listOf(0u, 6u) to Rational(45, 98), + listOf(1u, 6u) to Rational(54, 7), + listOf(2u, 6u) to Rational(1809, 35), + listOf(3u, 6u) to Rational(162), + listOf(4u, 6u) to Rational(405, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(0, 6), + listOf(1u) to Rational(14, 8), + listOf(2u) to Rational(-14, 2), + listOf(0u, 1u) to Rational(-3, 5), + listOf(1u, 1u) to Rational(11, 1), + listOf(2u, 1u) to Rational(3, 7), + listOf(0u, 2u) to Rational(-3, 7), + listOf(1u, 2u) to Rational(-18, 5), + listOf(2u, 2u) to Rational(-9, 1), + ), + )), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substitute(RationalField, bufferOf>()), + "test 6" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_Polynomial_substitute_RationalFunction_Buffer() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(4u) to Rational(-194071, 4900), + listOf(3u, 1u) to Rational(394811, 225), + listOf(2u, 2u) to Rational(-444183161, 66150), + listOf(1u, 3u) to Rational(70537618, 59535), + listOf(0u, 4u) to Rational(9655504, 2835), + ), + NumberedPolynomialAsIs( + listOf(4u) to Rational(9, 1), + listOf(3u, 1u) to Rational(61, 1), + listOf(2u, 2u) to Rational(2137, 36), + listOf(1u, 3u) to Rational(-1342, 9), + listOf(0u, 4u) to Rational(484, 9), + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(17, 7), + listOf(0u, 1u) to Rational(-13, 1), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(-18, 6), + listOf(0u, 1u) to Rational(11, 6), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(18, 5), + listOf(0u, 1u) to Rational(-16, 3), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(-4, 1), + ) + ), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-6443599, 10000), + listOf(1u) to Rational(166251223, 210000), + listOf(2u) to Rational(-4606805099, 3528000), + listOf(3u) to Rational(51204379, 19600), + listOf(4u) to Rational(-529045460659, 277830000), + listOf(5u) to Rational(2630836709, 1488375), + listOf(6u) to Rational(-42675691369, 25004700), + listOf(7u) to Rational(495825223, 1250235), + listOf(8u) to Rational(-22531756, 1750329), + listOf(0u, 1u) to Rational(-2526552797, 420000), + listOf(1u, 1u) to Rational(31108840471, 2520000), + listOf(2u, 1u) to Rational(-4789740847, 1102500), + listOf(3u, 1u) to Rational(186594307807, 11340000), + listOf(4u, 1u) to Rational(-11677815943, 1488375), + listOf(5u, 1u) to Rational(-181118486447, 27783000), + listOf(6u, 1u) to Rational(-16123292162, 14586075), + listOf(7u, 1u) to Rational(-140339343808, 26254935), + listOf(8u, 1u) to Rational(4570171616, 5250987), + listOf(0u, 2u) to Rational(-181436530573, 10080000), + listOf(1u, 2u) to Rational(6700437957491, 105840000), + listOf(2u, 2u) to Rational(-3527267461, 1417500), + listOf(3u, 2u) to Rational(-38084563451, 5556600), + listOf(4u, 2u) to Rational(-565662040631, 13891500), + listOf(5u, 2u) to Rational(-35479071126397, 583443000), + listOf(6u, 2u) to Rational(-11717559078469, 525098700), + listOf(7u, 2u) to Rational(-2043385293517, 225042300), + listOf(8u, 2u) to Rational(-3644439630451, 551353635), + listOf(0u, 3u) to Rational(-1760423269, 126000), + listOf(1u, 3u) to Rational(310176758299, 2352000), + listOf(2u, 3u) to Rational(-907229584837, 21168000), + listOf(3u, 3u) to Rational(-16717135885963, 95256000), + listOf(4u, 3u) to Rational(-43762928025353, 333396000), + listOf(5u, 3u) to Rational(-328427480571607, 3000564000), + listOf(6u, 3u) to Rational(-7722675917197, 210039480), + listOf(7u, 3u) to Rational(1713350137019, 1225230300), + listOf(8u, 3u) to Rational(156695935643, 31505922), + listOf(0u, 4u) to Rational(18362364269, 1008000), + listOf(1u, 4u) to Rational(955674858553, 10584000), + listOf(2u, 4u) to Rational(-71937470607371, 444528000), + listOf(3u, 4u) to Rational(-34097985615163, 95256000), + listOf(4u, 4u) to Rational(-340736178775883, 2000376000), + listOf(5u, 4u) to Rational(-511324523441897, 10501974000), + listOf(6u, 4u) to Rational(-125375649409151, 8821658160), + listOf(7u, 4u) to Rational(-2813518533421, 1575296100), + listOf(8u, 4u) to Rational(-17044089109, 5250987), + listOf(0u, 5u) to Rational(600086461, 20160), + listOf(1u, 5u) to Rational(-18959931367, 423360), + listOf(2u, 5u) to Rational(-9178804929607, 44452800), + listOf(3u, 5u) to Rational(-1460114275979, 5334336), + listOf(4u, 5u) to Rational(-342533479090169, 4200789600), + listOf(5u, 5u) to Rational(20335453022963, 4200789600), + listOf(6u, 5u) to Rational(-21649775090197, 6301184400), + listOf(7u, 5u) to Rational(-197301716069, 131274675), + listOf(8u, 5u) to Rational(18711357470, 15752961), + listOf(0u, 6u) to Rational(621417991, 100800), + listOf(1u, 6u) to Rational(-159236792977, 2116800), + listOf(2u, 6u) to Rational(-6602528890883, 66679200), + listOf(3u, 6u) to Rational(-1086091664047, 19051200), + listOf(4u, 6u) to Rational(3769375009003, 1680315840), + listOf(5u, 6u) to Rational(-12920385574769, 1050197400), + listOf(6u, 6u) to Rational(-90219591809287, 6301184400), + listOf(7u, 6u) to Rational(656361553391, 1575296100), + listOf(8u, 6u) to Rational(757900793, 2250423), + listOf(0u, 7u) to Rational(-100770017, 15120), + listOf(1u, 7u) to Rational(-316364851, 17640), + listOf(2u, 7u) to Rational(-85118560057, 6667920), + listOf(3u, 7u) to Rational(6286563719, 416745), + listOf(4u, 7u) to Rational(26803885301, 1714608), + listOf(5u, 7u) to Rational(-13767154393, 4286520), + listOf(6u, 7u) to Rational(-3875138933, 1224720), + listOf(7u, 7u) to Rational(65193755, 333396), + listOf(8u, 7u) to Rational(90974351, 2500470), + listOf(0u, 8u) to Rational(-3182197, 1260), + listOf(1u, 8u) to Rational(24899923, 8820), + listOf(2u, 8u) to Rational(-19999556, 19845), + listOf(3u, 8u) to Rational(3276587, 3969), + listOf(4u, 8u) to Rational(13719549239, 5000940), + listOf(5u, 8u) to Rational(-961839938, 1250235), + listOf(6u, 8u) to Rational(-198184871, 833490), + listOf(7u, 8u) to Rational(230659711, 5000940), + listOf(8u, 8u) to Rational(292447, 35721) + ), + NumberedPolynomialAsIs( + listOf() to Rational(9, 100), + listOf(1u) to Rational(-21, 50), + listOf(2u) to Rational(293, 700), + listOf(3u) to Rational(29, 210), + listOf(4u) to Rational(3233, 8820), + listOf(5u) to Rational(-289, 441), + listOf(6u) to Rational(-1, 9), + listOf(7u) to Rational(-20, 441), + listOf(8u) to Rational(100, 441), + listOf(0u, 1u) to Rational(-57, 80), + listOf(1u, 1u) to Rational(-121, 400), + listOf(2u, 1u) to Rational(37117, 8400), + listOf(3u, 1u) to Rational(-4853, 3150), + listOf(4u, 1u) to Rational(1166203, 132300), + listOf(5u, 1u) to Rational(-2708, 567), + listOf(6u, 1u) to Rational(-287159, 416745), + listOf(7u, 1u) to Rational(-478204, 83349), + listOf(8u, 1u) to Rational(176320, 83349), + listOf(0u, 2u) to Rational(-6239, 6400), + listOf(1u, 2u) to Rational(264211, 11200), + listOf(2u, 2u) to Rational(-1591999, 100800), + listOf(3u, 2u) to Rational(12450091, 529200), + listOf(4u, 2u) to Rational(9230759, 226800), + listOf(5u, 2u) to Rational(18995554, 2083725), + listOf(6u, 2u) to Rational(136706258, 6251175), + listOf(7u, 2u) to Rational(-120907496, 3750705), + listOf(8u, 2u) to Rational(117200176, 15752961), + listOf(0u, 3u) to Rational(5653, 320), + listOf(1u, 3u) to Rational(-130853, 8400), + listOf(2u, 3u) to Rational(-20939327, 151200), + listOf(3u, 3u) to Rational(2566691, 25200), + listOf(4u, 3u) to Rational(-68441519, 476280), + listOf(5u, 3u) to Rational(2462904247, 12502350), + listOf(6u, 3u) to Rational(353667161, 18753525), + listOf(7u, 3u) to Rational(-1689134372, 26254935), + listOf(8u, 3u) to Rational(35084104, 2250423), + listOf(0u, 4u) to Rational(-3587, 300), + listOf(1u, 4u) to Rational(-10513243, 33600), + listOf(2u, 4u) to Rational(30766733, 176400), + listOf(3u, 4u) to Rational(-65680021, 198450), + listOf(4u, 4u) to Rational(-8108910547, 20003760), + listOf(5u, 4u) to Rational(2922125159, 6251175), + listOf(6u, 4u) to Rational(-4245279943, 131274675), + listOf(7u, 4u) to Rational(-371946872, 3750705), + listOf(8u, 4u) to Rational(61286752, 2250423), + listOf(0u, 5u) to Rational(-20477, 160), + listOf(1u, 5u) to Rational(215741, 1120), + listOf(2u, 5u) to Rational(30785843, 31752), + listOf(3u, 5u) to Rational(-357495959, 317520), + listOf(4u, 5u) to Rational(-1611242993, 10001880), + listOf(5u, 5u) to Rational(345925495, 500094), + listOf(6u, 5u) to Rational(-755948411, 3750705), + listOf(7u, 5u) to Rational(-108643496, 1250235), + listOf(8u, 5u) to Rational(1122512, 35721), + listOf(0u, 6u) to Rational(358037, 2880), + listOf(1u, 6u) to Rational(3895837, 3360), + listOf(2u, 6u) to Rational(359419201, 1270080), + listOf(3u, 6u) to Rational(-158522587, 105840), + listOf(4u, 6u) to Rational(10909002599, 20003760), + listOf(5u, 6u) to Rational(76846972, 138915), + listOf(6u, 6u) to Rational(-327696553, 1250235), + listOf(7u, 6u) to Rational(-1687328, 35721), + listOf(8u, 6u) to Rational(1016836, 35721), + listOf(0u, 7u) to Rational(658, 3), + listOf(1u, 7u) to Rational(48035, 168), + listOf(2u, 7u) to Rational(-5777875, 5292), + listOf(3u, 7u) to Rational(-7893899, 10584), + listOf(4u, 7u) to Rational(10191652, 11907), + listOf(5u, 7u) to Rational(2920121, 23814), + listOf(6u, 7u) to Rational(-2699780, 11907), + listOf(7u, 7u) to Rational(4556, 441), + listOf(8u, 7u) to Rational(3440, 189), + listOf(0u, 8u) to Rational(64, 1), + listOf(1u, 8u) to Rational(-808, 7), + listOf(2u, 8u) to Rational(-360895, 1764), + listOf(3u, 8u) to Rational(257657, 882), + listOf(4u, 8u) to Rational(3779917, 15876), + listOf(5u, 8u) to Rational(-610279, 3969), + listOf(6u, 8u) to Rational(-25091, 441), + listOf(7u, 8u) to Rational(9560, 567), + listOf(8u, 8u) to Rational(400, 81) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 9), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(10, 9), + listOf(0u, 1u) to Rational(13, 3), + listOf(1u, 1u) to Rational(-12, 4), + listOf(2u, 1u) to Rational(3, 6), + listOf(0u, 2u) to Rational(2, 9), + listOf(1u, 2u) to Rational(7, 3), + listOf(2u, 2u) to Rational(16, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 2), + listOf(1u) to Rational(6, 2), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 1), + listOf(1u, 1u) to Rational(-11, 3), + listOf(2u, 1u) to Rational(7, 5), + listOf(0u, 2u) to Rational(8, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(17, 4), + ) + ) + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-6443599, 10000), + listOf(1u) to Rational(166251223, 210000), + listOf(2u) to Rational(-4606805099, 3528000), + listOf(3u) to Rational(51204379, 19600), + listOf(4u) to Rational(-529045460659, 277830000), + listOf(5u) to Rational(2630836709, 1488375), + listOf(6u) to Rational(-42675691369, 25004700), + listOf(7u) to Rational(495825223, 1250235), + listOf(8u) to Rational(-22531756, 1750329), + listOf(0u, 1u) to Rational(-2526552797, 420000), + listOf(1u, 1u) to Rational(31108840471, 2520000), + listOf(2u, 1u) to Rational(-4789740847, 1102500), + listOf(3u, 1u) to Rational(186594307807, 11340000), + listOf(4u, 1u) to Rational(-11677815943, 1488375), + listOf(5u, 1u) to Rational(-181118486447, 27783000), + listOf(6u, 1u) to Rational(-16123292162, 14586075), + listOf(7u, 1u) to Rational(-140339343808, 26254935), + listOf(8u, 1u) to Rational(4570171616, 5250987), + listOf(0u, 2u) to Rational(-181436530573, 10080000), + listOf(1u, 2u) to Rational(6700437957491, 105840000), + listOf(2u, 2u) to Rational(-3527267461, 1417500), + listOf(3u, 2u) to Rational(-38084563451, 5556600), + listOf(4u, 2u) to Rational(-565662040631, 13891500), + listOf(5u, 2u) to Rational(-35479071126397, 583443000), + listOf(6u, 2u) to Rational(-11717559078469, 525098700), + listOf(7u, 2u) to Rational(-2043385293517, 225042300), + listOf(8u, 2u) to Rational(-3644439630451, 551353635), + listOf(0u, 3u) to Rational(-1760423269, 126000), + listOf(1u, 3u) to Rational(310176758299, 2352000), + listOf(2u, 3u) to Rational(-907229584837, 21168000), + listOf(3u, 3u) to Rational(-16717135885963, 95256000), + listOf(4u, 3u) to Rational(-43762928025353, 333396000), + listOf(5u, 3u) to Rational(-328427480571607, 3000564000), + listOf(6u, 3u) to Rational(-7722675917197, 210039480), + listOf(7u, 3u) to Rational(1713350137019, 1225230300), + listOf(8u, 3u) to Rational(156695935643, 31505922), + listOf(0u, 4u) to Rational(18362364269, 1008000), + listOf(1u, 4u) to Rational(955674858553, 10584000), + listOf(2u, 4u) to Rational(-71937470607371, 444528000), + listOf(3u, 4u) to Rational(-34097985615163, 95256000), + listOf(4u, 4u) to Rational(-340736178775883, 2000376000), + listOf(5u, 4u) to Rational(-511324523441897, 10501974000), + listOf(6u, 4u) to Rational(-125375649409151, 8821658160), + listOf(7u, 4u) to Rational(-2813518533421, 1575296100), + listOf(8u, 4u) to Rational(-17044089109, 5250987), + listOf(0u, 5u) to Rational(600086461, 20160), + listOf(1u, 5u) to Rational(-18959931367, 423360), + listOf(2u, 5u) to Rational(-9178804929607, 44452800), + listOf(3u, 5u) to Rational(-1460114275979, 5334336), + listOf(4u, 5u) to Rational(-342533479090169, 4200789600), + listOf(5u, 5u) to Rational(20335453022963, 4200789600), + listOf(6u, 5u) to Rational(-21649775090197, 6301184400), + listOf(7u, 5u) to Rational(-197301716069, 131274675), + listOf(8u, 5u) to Rational(18711357470, 15752961), + listOf(0u, 6u) to Rational(621417991, 100800), + listOf(1u, 6u) to Rational(-159236792977, 2116800), + listOf(2u, 6u) to Rational(-6602528890883, 66679200), + listOf(3u, 6u) to Rational(-1086091664047, 19051200), + listOf(4u, 6u) to Rational(3769375009003, 1680315840), + listOf(5u, 6u) to Rational(-12920385574769, 1050197400), + listOf(6u, 6u) to Rational(-90219591809287, 6301184400), + listOf(7u, 6u) to Rational(656361553391, 1575296100), + listOf(8u, 6u) to Rational(757900793, 2250423), + listOf(0u, 7u) to Rational(-100770017, 15120), + listOf(1u, 7u) to Rational(-316364851, 17640), + listOf(2u, 7u) to Rational(-85118560057, 6667920), + listOf(3u, 7u) to Rational(6286563719, 416745), + listOf(4u, 7u) to Rational(26803885301, 1714608), + listOf(5u, 7u) to Rational(-13767154393, 4286520), + listOf(6u, 7u) to Rational(-3875138933, 1224720), + listOf(7u, 7u) to Rational(65193755, 333396), + listOf(8u, 7u) to Rational(90974351, 2500470), + listOf(0u, 8u) to Rational(-3182197, 1260), + listOf(1u, 8u) to Rational(24899923, 8820), + listOf(2u, 8u) to Rational(-19999556, 19845), + listOf(3u, 8u) to Rational(3276587, 3969), + listOf(4u, 8u) to Rational(13719549239, 5000940), + listOf(5u, 8u) to Rational(-961839938, 1250235), + listOf(6u, 8u) to Rational(-198184871, 833490), + listOf(7u, 8u) to Rational(230659711, 5000940), + listOf(8u, 8u) to Rational(292447, 35721) + ), + NumberedPolynomialAsIs( + listOf() to Rational(9, 100), + listOf(1u) to Rational(-21, 50), + listOf(2u) to Rational(293, 700), + listOf(3u) to Rational(29, 210), + listOf(4u) to Rational(3233, 8820), + listOf(5u) to Rational(-289, 441), + listOf(6u) to Rational(-1, 9), + listOf(7u) to Rational(-20, 441), + listOf(8u) to Rational(100, 441), + listOf(0u, 1u) to Rational(-57, 80), + listOf(1u, 1u) to Rational(-121, 400), + listOf(2u, 1u) to Rational(37117, 8400), + listOf(3u, 1u) to Rational(-4853, 3150), + listOf(4u, 1u) to Rational(1166203, 132300), + listOf(5u, 1u) to Rational(-2708, 567), + listOf(6u, 1u) to Rational(-287159, 416745), + listOf(7u, 1u) to Rational(-478204, 83349), + listOf(8u, 1u) to Rational(176320, 83349), + listOf(0u, 2u) to Rational(-6239, 6400), + listOf(1u, 2u) to Rational(264211, 11200), + listOf(2u, 2u) to Rational(-1591999, 100800), + listOf(3u, 2u) to Rational(12450091, 529200), + listOf(4u, 2u) to Rational(9230759, 226800), + listOf(5u, 2u) to Rational(18995554, 2083725), + listOf(6u, 2u) to Rational(136706258, 6251175), + listOf(7u, 2u) to Rational(-120907496, 3750705), + listOf(8u, 2u) to Rational(117200176, 15752961), + listOf(0u, 3u) to Rational(5653, 320), + listOf(1u, 3u) to Rational(-130853, 8400), + listOf(2u, 3u) to Rational(-20939327, 151200), + listOf(3u, 3u) to Rational(2566691, 25200), + listOf(4u, 3u) to Rational(-68441519, 476280), + listOf(5u, 3u) to Rational(2462904247, 12502350), + listOf(6u, 3u) to Rational(353667161, 18753525), + listOf(7u, 3u) to Rational(-1689134372, 26254935), + listOf(8u, 3u) to Rational(35084104, 2250423), + listOf(0u, 4u) to Rational(-3587, 300), + listOf(1u, 4u) to Rational(-10513243, 33600), + listOf(2u, 4u) to Rational(30766733, 176400), + listOf(3u, 4u) to Rational(-65680021, 198450), + listOf(4u, 4u) to Rational(-8108910547, 20003760), + listOf(5u, 4u) to Rational(2922125159, 6251175), + listOf(6u, 4u) to Rational(-4245279943, 131274675), + listOf(7u, 4u) to Rational(-371946872, 3750705), + listOf(8u, 4u) to Rational(61286752, 2250423), + listOf(0u, 5u) to Rational(-20477, 160), + listOf(1u, 5u) to Rational(215741, 1120), + listOf(2u, 5u) to Rational(30785843, 31752), + listOf(3u, 5u) to Rational(-357495959, 317520), + listOf(4u, 5u) to Rational(-1611242993, 10001880), + listOf(5u, 5u) to Rational(345925495, 500094), + listOf(6u, 5u) to Rational(-755948411, 3750705), + listOf(7u, 5u) to Rational(-108643496, 1250235), + listOf(8u, 5u) to Rational(1122512, 35721), + listOf(0u, 6u) to Rational(358037, 2880), + listOf(1u, 6u) to Rational(3895837, 3360), + listOf(2u, 6u) to Rational(359419201, 1270080), + listOf(3u, 6u) to Rational(-158522587, 105840), + listOf(4u, 6u) to Rational(10909002599, 20003760), + listOf(5u, 6u) to Rational(76846972, 138915), + listOf(6u, 6u) to Rational(-327696553, 1250235), + listOf(7u, 6u) to Rational(-1687328, 35721), + listOf(8u, 6u) to Rational(1016836, 35721), + listOf(0u, 7u) to Rational(658, 3), + listOf(1u, 7u) to Rational(48035, 168), + listOf(2u, 7u) to Rational(-5777875, 5292), + listOf(3u, 7u) to Rational(-7893899, 10584), + listOf(4u, 7u) to Rational(10191652, 11907), + listOf(5u, 7u) to Rational(2920121, 23814), + listOf(6u, 7u) to Rational(-2699780, 11907), + listOf(7u, 7u) to Rational(4556, 441), + listOf(8u, 7u) to Rational(3440, 189), + listOf(0u, 8u) to Rational(64, 1), + listOf(1u, 8u) to Rational(-808, 7), + listOf(2u, 8u) to Rational(-360895, 1764), + listOf(3u, 8u) to Rational(257657, 882), + listOf(4u, 8u) to Rational(3779917, 15876), + listOf(5u, 8u) to Rational(-610279, 3969), + listOf(6u, 8u) to Rational(-25091, 441), + listOf(7u, 8u) to Rational(9560, 567), + listOf(8u, 8u) to Rational(400, 81) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(18, 5), + listOf(1u) to Rational(-17, 5), + listOf(2u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(-5, 1), + listOf(2u, 1u) to Rational(-9, 1), + listOf(0u, 2u) to Rational(-8, 8), + listOf(1u, 2u) to Rational(2, 7), + listOf(2u, 2u) to Rational(-13, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-4, 8), + listOf(1u) to Rational(15, 9), + listOf(2u) to Rational(-10, 9), + listOf(0u, 1u) to Rational(5, 3), + listOf(1u, 1u) to Rational(4, 1), + listOf(2u, 1u) to Rational(-2, 7), + listOf(0u, 2u) to Rational(2, 2), + listOf(1u, 2u) to Rational(-5, 7), + listOf(2u, 2u) to Rational(-18, 9), + ) + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-66677, 3500), + listOf(1u) to Rational(-206281, 10500), + listOf(2u) to Rational(-412567, 7056), + listOf(3u) to Rational(-310081, 11025), + listOf(4u) to Rational(-575996, 15435), + listOf(0u, 1u) to Rational(-573701, 4200), + listOf(1u, 1u) to Rational(-2239001, 25200), + listOf(2u, 1u) to Rational(-8817889, 132300), + listOf(3u, 1u) to Rational(2317919, 44100), + listOf(4u, 1u) to Rational(1169471, 6615), + listOf(0u, 2u) to Rational(-4057819, 33600), + listOf(1u, 2u) to Rational(1373311, 12600), + listOf(2u, 2u) to Rational(32433493, 52920), + listOf(3u, 2u) to Rational(4998053, 33075), + listOf(4u, 2u) to Rational(-2147779, 8820), + listOf(0u, 3u) to Rational(2018481, 2240), + listOf(1u, 3u) to Rational(941713, 1440), + listOf(2u, 3u) to Rational(183749, 6615), + listOf(3u, 3u) to Rational(-4631023, 15876), + listOf(4u, 3u) to Rational(25609336, 178605), + listOf(0u, 4u) to Rational(11886431, 6720), + listOf(1u, 4u) to Rational(18433, 504), + listOf(2u, 4u) to Rational(-39613331, 45360), + listOf(3u, 4u) to Rational(681619, 5670), + listOf(4u, 4u) to Rational(-864841, 20412), + listOf(0u, 5u) to Rational(343535, 1008), + listOf(1u, 5u) to Rational(-33583, 72), + listOf(2u, 5u) to Rational(1194625, 9072), + listOf(3u, 5u) to Rational(-62917, 2268), + listOf(4u, 5u) to Rational(157645, 10206), + listOf(0u, 6u) to Rational(-1381, 3), + listOf(1u, 6u) to Rational(919, 36), + listOf(2u, 6u) to Rational(-3053, 36), + listOf(3u, 6u) to Rational(2125, 324), + listOf(4u, 6u) to Rational(-236, 243) + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(1, 4), + listOf(1u) to Rational(-5, 3), + listOf(2u) to Rational(35, 9), + listOf(3u) to Rational(-100, 27), + listOf(4u) to Rational(100, 81), + listOf(0u, 1u) to Rational(-5, 3), + listOf(1u, 1u) to Rational(14, 9), + listOf(2u, 1u) to Rational(1874, 189), + listOf(3u, 1u) to Rational(-620, 63), + listOf(4u, 1u) to Rational(40, 63), + listOf(0u, 2u) to Rational(16, 9), + listOf(1u, 2u) to Rational(365, 21), + listOf(2u, 2u) to Rational(112, 9), + listOf(3u, 2u) to Rational(-464, 63), + listOf(4u, 2u) to Rational(1996, 441), + listOf(0u, 3u) to Rational(10, 3), + listOf(1u, 3u) to Rational(118, 21), + listOf(2u, 3u) to Rational(-272, 21), + listOf(3u, 3u) to Rational(-764, 49), + listOf(4u, 3u) to Rational(8, 7), + listOf(0u, 4u) to Rational(1, 1), + listOf(1u, 4u) to Rational(-10, 7), + listOf(2u, 4u) to Rational(-171, 49), + listOf(3u, 4u) to Rational(20, 7), + listOf(4u, 4u) to Rational(4, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(17, 5), + listOf(1u) to Rational(11, 6), + listOf(2u) to Rational(14, 3), + listOf(0u, 1u) to Rational(17, 1), + listOf(1u, 1u) to Rational(12, 3), + listOf(2u, 1u) to Rational(-6, 2), + listOf(0u, 2u) to Rational(17, 1), + listOf(1u, 2u) to Rational(-4, 3), + listOf(2u, 2u) to Rational(2, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(3, 5), + listOf(1u) to Rational(3, 5), + listOf(2u) to Rational(3, 7), + listOf(0u, 1u) to Rational(-3, 8), + listOf(1u, 1u) to Rational(-1, 1), + listOf(2u, 1u) to Rational(17, 9), + listOf(0u, 2u) to Rational(-8, 1), + listOf(1u, 2u) to Rational(6, 4), + listOf(2u, 2u) to Rational(10, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ), + NumberedPolynomialAsIs(listOf() to Rational(0, 1), + listOf() to Rational(0, 1) + ) + ), + NumberedPolynomialAsIs( + listOf() to Rational(15, 7), + listOf(1u) to Rational(1, 5), + listOf(2u) to Rational(-7, 4), + listOf(0u, 1u) to Rational(-1, 9), + listOf(1u, 1u) to Rational(-2, 7), + listOf(2u, 1u) to Rational(17, 3), + listOf(0u, 2u) to Rational(2, 6), + listOf(1u, 2u) to Rational(-17, 6), + listOf(2u, 2u) to Rational(-6, 2), + ).substitute(RationalField, bufferOf>()), + "test 6" + ) + } + @Test + fun test_RationalFunction_substitute_Double_Buffer() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs(emptyList() to 0.0), + NumberedPolynomialAsIs(emptyList() to 1.0), + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ), + NumberedPolynomialAsIs( + listOf() to 1.0, + ) + ).substitute(bufferOf( + 1.0 + )), + 0.001, + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(bufferOf()), + 0.001, + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 151.1502229133916, + listOf(0u, 1u) to -262.3790170577034, + listOf(0u, 2u) to 102.5097937392923, + ), + NumberedPolynomialAsIs( + listOf() to -367.9969733169944, + listOf(0u, 1u) to 112.4911133334554, + listOf(0u, 2u) to -469.755906895345, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(bufferOf( + -8.11707689492641, + )), + 0.001, + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 7.321261307532708, + ), + NumberedPolynomialAsIs( + listOf() to -575.6325831127576, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(bufferOf( + -8.11707689492641, + 0.795265651276015, + )), + 0.001, + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 7.321261307532708, + ), + NumberedPolynomialAsIs( + listOf() to -575.6325831127576, + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substitute(bufferOf( + -8.11707689492641, + 0.795265651276015, + 0.9211194782050933 + )), + 0.001, + "test 5" + ) + } + @Test + fun test_RationalFunction_substitute_Constant_Buffer() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ).substitute(RationalField, bufferOf( + Rational(1) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(22047, 2450), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2204953, 147000), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, bufferOf( + Rational(7, 5), + Rational(-13, 7), + Rational(-16, 4), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(22047, 2450), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2204953, 147000), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, bufferOf( + Rational(7, 5), + Rational(-13, 7), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-939, 200), + listOf(0u, 1u) to Rational(123, 50), + listOf(0u, 2u) to Rational(1059, 200) + ), + NumberedPolynomialAsIs( + listOf() to Rational(121, 25), + listOf(0u, 1u) to Rational(-949, 375), + listOf(0u, 2u) to Rational(-1423, 200) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, bufferOf( + Rational(7, 5), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substitute(RationalField, bufferOf()), + "test 5" + ) + } + @Test + fun test_RationalFunction_substitute_Polynomial_Buffer() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(211, 4), + listOf(2u) to Rational(88, 3), + listOf(3u) to Rational(-63, 8), + listOf(4u) to Rational(441, 16), + listOf(0u, 1u) to Rational(-671, 15), + listOf(1u, 1u) to Rational(-551, 21), + listOf(2u, 1u) to Rational(279, 25), + listOf(3u, 1u) to Rational(231, 20), + listOf(0u, 2u) to Rational(-1436, 1575), + listOf(1u, 2u) to Rational(2471, 250), + listOf(2u, 2u) to Rational(-4919, 100), + listOf(0u, 3u) to Rational(-1464, 125), + listOf(1u, 3u) to Rational(-264, 25), + listOf(0u, 4u) to Rational(576, 25), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(-9, 4), + listOf(2u) to Rational(943, 8), + listOf(3u) to Rational(117, 8), + listOf(4u) to Rational(147, 16), + listOf(0u, 1u) to Rational(289, 90), + listOf(1u, 1u) to Rational(-2692, 15), + listOf(2u, 1u) to Rational(-1629, 140), + listOf(3u, 1u) to Rational(77, 20), + listOf(0u, 2u) to Rational(6187, 75), + listOf(1u, 2u) to Rational(-2879, 175), + listOf(2u, 2u) to Rational(-4919, 300), + listOf(0u, 3u) to Rational(336, 25), + listOf(1u, 3u) to Rational(-88, 25), + listOf(0u, 4u) to Rational(192, 25), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf(1u) to Rational(3, 2), + listOf(0u, 1u) to Rational(8, 5), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-3, 1), + ) + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1202861, 210), + listOf(1u) to Rational(-215117, 45), + listOf(2u) to Rational(10889651, 19845), + listOf(3u) to Rational(-3503956, 6615), + listOf(4u) to Rational(809066, 2205), + listOf(5u) to Rational(-9056, 735), + listOf(6u) to Rational(5396, 315), + listOf(7u) to Rational(-752, 147), + listOf(8u) to Rational(16, 49), + listOf(0u, 1u) to Rational(1738469, 1470), + listOf(1u, 1u) to Rational(-926238703, 52920), + listOf(2u, 1u) to Rational(-44113982, 6615), + listOf(3u, 1u) to Rational(10423519, 5292), + listOf(4u, 1u) to Rational(3769712, 2205), + listOf(5u, 1u) to Rational(8905046, 6615), + listOf(6u, 1u) to Rational(1186972, 6615), + listOf(7u, 1u) to Rational(22124, 441), + listOf(8u, 1u) to Rational(-1504, 147), + listOf(0u, 2u) to Rational(-54723628, 2205), + listOf(1u, 2u) to Rational(70109407, 1323), + listOf(2u, 2u) to Rational(151072591, 17640), + listOf(3u, 2u) to Rational(1216428107, 52920), + listOf(4u, 2u) to Rational(2587873193, 317520), + listOf(5u, 2u) to Rational(393536369, 79380), + listOf(6u, 2u) to Rational(137614937, 79380), + listOf(7u, 2u) to Rational(566866, 1323), + listOf(8u, 2u) to Rational(41848, 441), + listOf(0u, 3u) to Rational(-19470406, 2205), + listOf(1u, 3u) to Rational(72514195, 882), + listOf(2u, 3u) to Rational(-78090707, 1764), + listOf(3u, 3u) to Rational(-1988237707, 26460), + listOf(4u, 3u) to Rational(-802137919, 17640), + listOf(5u, 3u) to Rational(-139989463, 5880), + listOf(6u, 3u) to Rational(-26066641, 3780), + listOf(7u, 3u) to Rational(-2363369, 1323), + listOf(8u, 3u) to Rational(-108280, 441), + listOf(0u, 4u) to Rational(14878516, 441), + listOf(1u, 4u) to Rational(-253416724, 2205), + listOf(2u, 4u) to Rational(16699157, 840), + listOf(3u, 4u) to Rational(-105220979, 13230), + listOf(4u, 4u) to Rational(208266383, 5880), + listOf(5u, 4u) to Rational(650135309, 26460), + listOf(6u, 4u) to Rational(123808663, 11760), + listOf(7u, 4u) to Rational(8563385, 2646), + listOf(8u, 4u) to Rational(19721, 49), + listOf(0u, 5u) to Rational(675645, 49), + listOf(1u, 5u) to Rational(-70554077, 588), + listOf(2u, 5u) to Rational(157884029, 980), + listOf(3u, 5u) to Rational(489548623, 4410), + listOf(4u, 5u) to Rational(148540519, 17640), + listOf(5u, 5u) to Rational(-5559551, 392), + listOf(6u, 5u) to Rational(-18335711, 1470), + listOf(7u, 5u) to Rational(-38437, 9), + listOf(8u, 5u) to Rational(-29620, 63), + listOf(0u, 6u) to Rational(-727625, 49), + listOf(1u, 6u) to Rational(7046685, 98), + listOf(2u, 6u) to Rational(-334814231, 7056), + listOf(3u, 6u) to Rational(-243971737, 17640), + listOf(4u, 6u) to Rational(-571116659, 35280), + listOf(5u, 6u) to Rational(567538, 315), + listOf(6u, 6u) to Rational(3199768, 315), + listOf(7u, 6u) to Rational(227744, 63), + listOf(8u, 6u) to Rational(23116, 63), + listOf(0u, 7u) to Rational(-27500, 7), + listOf(1u, 7u) to Rational(120125, 3), + listOf(2u, 7u) to Rational(-279200, 3), + listOf(3u, 7u) to Rational(-100160, 7), + listOf(4u, 7u) to Rational(920452, 21), + listOf(5u, 7u) to Rational(226481, 21), + listOf(6u, 7u) to Rational(-34428, 7), + listOf(7u, 7u) to Rational(-6232, 3), + listOf(8u, 7u) to Rational(-608, 3), + listOf(0u, 8u) to Rational(2500, 1), + listOf(1u, 8u) to Rational(-19000, 1), + listOf(2u, 8u) to Rational(37900, 1), + listOf(3u, 8u) to Rational(-1840, 1), + listOf(4u, 8u) to Rational(-17876, 1), + listOf(5u, 8u) to Rational(-1240, 1), + listOf(6u, 8u) to Rational(2788, 1), + listOf(7u, 8u) to Rational(800, 1), + listOf(8u, 8u) to Rational(64, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(162487, 63), + listOf(1u) to Rational(-92713, 54), + listOf(2u) to Rational(802436, 1323), + listOf(3u) to Rational(-55088, 441), + listOf(4u) to Rational(1404034, 9261), + listOf(5u) to Rational(-5804, 1029), + listOf(6u) to Rational(51556, 9261), + listOf(7u) to Rational(-752, 441), + listOf(8u) to Rational(16, 147), + listOf(0u, 1u) to Rational(296071, 441), + listOf(1u, 1u) to Rational(-4991281, 882), + listOf(2u, 1u) to Rational(-18702811, 9261), + listOf(3u, 1u) to Rational(40759043, 27783), + listOf(4u, 1u) to Rational(19768501, 27783), + listOf(5u, 1u) to Rational(14307337, 27783), + listOf(6u, 1u) to Rational(1655684, 27783), + listOf(7u, 1u) to Rational(22124, 1323), + listOf(8u, 1u) to Rational(-1504, 441), + listOf(0u, 2u) to Rational(-27667474, 3087), + listOf(1u, 2u) to Rational(265605901, 12348), + listOf(2u, 2u) to Rational(160360775, 98784), + listOf(3u, 2u) to Rational(1169992093, 148176), + listOf(4u, 2u) to Rational(3978014077, 1333584), + listOf(5u, 2u) to Rational(567058123, 333396), + listOf(6u, 2u) to Rational(205132579, 333396), + listOf(7u, 2u) to Rational(566866, 3969), + listOf(8u, 2u) to Rational(41848, 1323), + listOf(0u, 3u) to Rational(-2228822, 1029), + listOf(1u, 3u) to Rational(80179390, 3087), + listOf(2u, 3u) to Rational(-1378630487, 74088), + listOf(3u, 3u) to Rational(-3385811693, 111132), + listOf(4u, 3u) to Rational(-820686977, 49392), + listOf(5u, 3u) to Rational(-89101027, 10584), + listOf(6u, 3u) to Rational(-37847387, 15876), + listOf(7u, 3u) to Rational(-2363369, 3969), + listOf(8u, 3u) to Rational(-108280, 1323), + listOf(0u, 4u) to Rational(12619982, 1029), + listOf(1u, 4u) to Rational(-277723177, 6174), + listOf(2u, 4u) to Rational(649414169, 49392), + listOf(3u, 4u) to Rational(14457595, 63504), + listOf(4u, 4u) to Rational(139270339, 10584), + listOf(5u, 4u) to Rational(140367961, 15876), + listOf(6u, 4u) to Rational(25467083, 7056), + listOf(7u, 4u) to Rational(8563385, 7938), + listOf(8u, 4u) to Rational(19721, 147), + listOf(0u, 5u) to Rational(643850, 147), + listOf(1u, 5u) to Rational(-11818025, 294), + listOf(2u, 5u) to Rational(33963203, 588), + listOf(3u, 5u) to Rational(207216235, 5292), + listOf(4u, 5u) to Rational(2861021, 1512), + listOf(5u, 5u) to Rational(-6302335, 1176), + listOf(6u, 5u) to Rational(-3738587, 882), + listOf(7u, 5u) to Rational(-38437, 27), + listOf(8u, 5u) to Rational(-29620, 189), + listOf(0u, 6u) to Rational(-248725, 49), + listOf(1u, 6u) to Rational(2478535, 98), + listOf(2u, 6u) to Rational(-399721367, 21168), + listOf(3u, 6u) to Rational(-54309317, 10584), + listOf(4u, 6u) to Rational(-95398327, 21168), + listOf(5u, 6u) to Rational(173750, 189), + listOf(6u, 6u) to Rational(92216, 27), + listOf(7u, 6u) to Rational(227744, 189), + listOf(8u, 6u) to Rational(23116, 189), + listOf(0u, 7u) to Rational(-27500, 21), + listOf(1u, 7u) to Rational(120125, 9), + listOf(2u, 7u) to Rational(-279200, 9), + listOf(3u, 7u) to Rational(-100160, 21), + listOf(4u, 7u) to Rational(920452, 63), + listOf(5u, 7u) to Rational(226481, 63), + listOf(6u, 7u) to Rational(-11476, 7), + listOf(7u, 7u) to Rational(-6232, 9), + listOf(8u, 7u) to Rational(-608, 9), + listOf(0u, 8u) to Rational(2500, 3), + listOf(1u, 8u) to Rational(-19000, 3), + listOf(2u, 8u) to Rational(37900, 3), + listOf(3u, 8u) to Rational(-1840, 3), + listOf(4u, 8u) to Rational(-17876, 3), + listOf(5u, 8u) to Rational(-1240, 3), + listOf(6u, 8u) to Rational(2788, 3), + listOf(7u, 8u) to Rational(800, 3), + listOf(8u, 8u) to Rational(64, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 1), + listOf(1u) to Rational(-9, 8), + listOf(2u) to Rational(17, 5), + listOf(0u, 1u) to Rational(-2, 3), + listOf(1u, 1u) to Rational(1, 5), + listOf(2u, 1u) to Rational(-11, 7), + listOf(0u, 2u) to Rational(13, 6), + listOf(1u, 2u) to Rational(-15, 2), + listOf(2u, 2u) to Rational(-14, 4), + ) + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1202861, 210), + listOf(1u) to Rational(-215117, 45), + listOf(2u) to Rational(10889651, 19845), + listOf(3u) to Rational(-3503956, 6615), + listOf(4u) to Rational(809066, 2205), + listOf(5u) to Rational(-9056, 735), + listOf(6u) to Rational(5396, 315), + listOf(7u) to Rational(-752, 147), + listOf(8u) to Rational(16, 49), + listOf(0u, 1u) to Rational(1738469, 1470), + listOf(1u, 1u) to Rational(-926238703, 52920), + listOf(2u, 1u) to Rational(-44113982, 6615), + listOf(3u, 1u) to Rational(10423519, 5292), + listOf(4u, 1u) to Rational(3769712, 2205), + listOf(5u, 1u) to Rational(8905046, 6615), + listOf(6u, 1u) to Rational(1186972, 6615), + listOf(7u, 1u) to Rational(22124, 441), + listOf(8u, 1u) to Rational(-1504, 147), + listOf(0u, 2u) to Rational(-54723628, 2205), + listOf(1u, 2u) to Rational(70109407, 1323), + listOf(2u, 2u) to Rational(151072591, 17640), + listOf(3u, 2u) to Rational(1216428107, 52920), + listOf(4u, 2u) to Rational(2587873193, 317520), + listOf(5u, 2u) to Rational(393536369, 79380), + listOf(6u, 2u) to Rational(137614937, 79380), + listOf(7u, 2u) to Rational(566866, 1323), + listOf(8u, 2u) to Rational(41848, 441), + listOf(0u, 3u) to Rational(-19470406, 2205), + listOf(1u, 3u) to Rational(72514195, 882), + listOf(2u, 3u) to Rational(-78090707, 1764), + listOf(3u, 3u) to Rational(-1988237707, 26460), + listOf(4u, 3u) to Rational(-802137919, 17640), + listOf(5u, 3u) to Rational(-139989463, 5880), + listOf(6u, 3u) to Rational(-26066641, 3780), + listOf(7u, 3u) to Rational(-2363369, 1323), + listOf(8u, 3u) to Rational(-108280, 441), + listOf(0u, 4u) to Rational(14878516, 441), + listOf(1u, 4u) to Rational(-253416724, 2205), + listOf(2u, 4u) to Rational(16699157, 840), + listOf(3u, 4u) to Rational(-105220979, 13230), + listOf(4u, 4u) to Rational(208266383, 5880), + listOf(5u, 4u) to Rational(650135309, 26460), + listOf(6u, 4u) to Rational(123808663, 11760), + listOf(7u, 4u) to Rational(8563385, 2646), + listOf(8u, 4u) to Rational(19721, 49), + listOf(0u, 5u) to Rational(675645, 49), + listOf(1u, 5u) to Rational(-70554077, 588), + listOf(2u, 5u) to Rational(157884029, 980), + listOf(3u, 5u) to Rational(489548623, 4410), + listOf(4u, 5u) to Rational(148540519, 17640), + listOf(5u, 5u) to Rational(-5559551, 392), + listOf(6u, 5u) to Rational(-18335711, 1470), + listOf(7u, 5u) to Rational(-38437, 9), + listOf(8u, 5u) to Rational(-29620, 63), + listOf(0u, 6u) to Rational(-727625, 49), + listOf(1u, 6u) to Rational(7046685, 98), + listOf(2u, 6u) to Rational(-334814231, 7056), + listOf(3u, 6u) to Rational(-243971737, 17640), + listOf(4u, 6u) to Rational(-571116659, 35280), + listOf(5u, 6u) to Rational(567538, 315), + listOf(6u, 6u) to Rational(3199768, 315), + listOf(7u, 6u) to Rational(227744, 63), + listOf(8u, 6u) to Rational(23116, 63), + listOf(0u, 7u) to Rational(-27500, 7), + listOf(1u, 7u) to Rational(120125, 3), + listOf(2u, 7u) to Rational(-279200, 3), + listOf(3u, 7u) to Rational(-100160, 7), + listOf(4u, 7u) to Rational(920452, 21), + listOf(5u, 7u) to Rational(226481, 21), + listOf(6u, 7u) to Rational(-34428, 7), + listOf(7u, 7u) to Rational(-6232, 3), + listOf(8u, 7u) to Rational(-608, 3), + listOf(0u, 8u) to Rational(2500, 1), + listOf(1u, 8u) to Rational(-19000, 1), + listOf(2u, 8u) to Rational(37900, 1), + listOf(3u, 8u) to Rational(-1840, 1), + listOf(4u, 8u) to Rational(-17876, 1), + listOf(5u, 8u) to Rational(-1240, 1), + listOf(6u, 8u) to Rational(2788, 1), + listOf(7u, 8u) to Rational(800, 1), + listOf(8u, 8u) to Rational(64, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(162487, 63), + listOf(1u) to Rational(-92713, 54), + listOf(2u) to Rational(802436, 1323), + listOf(3u) to Rational(-55088, 441), + listOf(4u) to Rational(1404034, 9261), + listOf(5u) to Rational(-5804, 1029), + listOf(6u) to Rational(51556, 9261), + listOf(7u) to Rational(-752, 441), + listOf(8u) to Rational(16, 147), + listOf(0u, 1u) to Rational(296071, 441), + listOf(1u, 1u) to Rational(-4991281, 882), + listOf(2u, 1u) to Rational(-18702811, 9261), + listOf(3u, 1u) to Rational(40759043, 27783), + listOf(4u, 1u) to Rational(19768501, 27783), + listOf(5u, 1u) to Rational(14307337, 27783), + listOf(6u, 1u) to Rational(1655684, 27783), + listOf(7u, 1u) to Rational(22124, 1323), + listOf(8u, 1u) to Rational(-1504, 441), + listOf(0u, 2u) to Rational(-27667474, 3087), + listOf(1u, 2u) to Rational(265605901, 12348), + listOf(2u, 2u) to Rational(160360775, 98784), + listOf(3u, 2u) to Rational(1169992093, 148176), + listOf(4u, 2u) to Rational(3978014077, 1333584), + listOf(5u, 2u) to Rational(567058123, 333396), + listOf(6u, 2u) to Rational(205132579, 333396), + listOf(7u, 2u) to Rational(566866, 3969), + listOf(8u, 2u) to Rational(41848, 1323), + listOf(0u, 3u) to Rational(-2228822, 1029), + listOf(1u, 3u) to Rational(80179390, 3087), + listOf(2u, 3u) to Rational(-1378630487, 74088), + listOf(3u, 3u) to Rational(-3385811693, 111132), + listOf(4u, 3u) to Rational(-820686977, 49392), + listOf(5u, 3u) to Rational(-89101027, 10584), + listOf(6u, 3u) to Rational(-37847387, 15876), + listOf(7u, 3u) to Rational(-2363369, 3969), + listOf(8u, 3u) to Rational(-108280, 1323), + listOf(0u, 4u) to Rational(12619982, 1029), + listOf(1u, 4u) to Rational(-277723177, 6174), + listOf(2u, 4u) to Rational(649414169, 49392), + listOf(3u, 4u) to Rational(14457595, 63504), + listOf(4u, 4u) to Rational(139270339, 10584), + listOf(5u, 4u) to Rational(140367961, 15876), + listOf(6u, 4u) to Rational(25467083, 7056), + listOf(7u, 4u) to Rational(8563385, 7938), + listOf(8u, 4u) to Rational(19721, 147), + listOf(0u, 5u) to Rational(643850, 147), + listOf(1u, 5u) to Rational(-11818025, 294), + listOf(2u, 5u) to Rational(33963203, 588), + listOf(3u, 5u) to Rational(207216235, 5292), + listOf(4u, 5u) to Rational(2861021, 1512), + listOf(5u, 5u) to Rational(-6302335, 1176), + listOf(6u, 5u) to Rational(-3738587, 882), + listOf(7u, 5u) to Rational(-38437, 27), + listOf(8u, 5u) to Rational(-29620, 189), + listOf(0u, 6u) to Rational(-248725, 49), + listOf(1u, 6u) to Rational(2478535, 98), + listOf(2u, 6u) to Rational(-399721367, 21168), + listOf(3u, 6u) to Rational(-54309317, 10584), + listOf(4u, 6u) to Rational(-95398327, 21168), + listOf(5u, 6u) to Rational(173750, 189), + listOf(6u, 6u) to Rational(92216, 27), + listOf(7u, 6u) to Rational(227744, 189), + listOf(8u, 6u) to Rational(23116, 189), + listOf(0u, 7u) to Rational(-27500, 21), + listOf(1u, 7u) to Rational(120125, 9), + listOf(2u, 7u) to Rational(-279200, 9), + listOf(3u, 7u) to Rational(-100160, 21), + listOf(4u, 7u) to Rational(920452, 63), + listOf(5u, 7u) to Rational(226481, 63), + listOf(6u, 7u) to Rational(-11476, 7), + listOf(7u, 7u) to Rational(-6232, 9), + listOf(8u, 7u) to Rational(-608, 9), + listOf(0u, 8u) to Rational(2500, 3), + listOf(1u, 8u) to Rational(-19000, 3), + listOf(2u, 8u) to Rational(37900, 3), + listOf(3u, 8u) to Rational(-1840, 3), + listOf(4u, 8u) to Rational(-17876, 3), + listOf(5u, 8u) to Rational(-1240, 3), + listOf(6u, 8u) to Rational(2788, 3), + listOf(7u, 8u) to Rational(800, 3), + listOf(8u, 8u) to Rational(64, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(8, 2), + listOf(1u) to Rational(-15, 5), + listOf(2u) to Rational(2, 7), + listOf(0u, 1u) to Rational(-18, 7), + listOf(1u, 1u) to Rational(-16, 6), + listOf(2u, 1u) to Rational(-13, 3), + listOf(0u, 2u) to Rational(-5, 1), + listOf(1u, 2u) to Rational(17, 1), + listOf(2u, 2u) to Rational(8, 2), + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-409, 6), + listOf(1u) to Rational(-376, 9), + listOf(2u) to Rational(-1781, 81), + listOf(3u) to Rational(-128, 27), + listOf(4u) to Rational(-8, 9), + listOf(0u, 1u) to Rational(18701, 210), + listOf(1u, 1u) to Rational(614183, 7560), + listOf(2u, 1u) to Rational(90941, 1890), + listOf(3u, 1u) to Rational(1802, 135), + listOf(4u, 1u) to Rational(112, 45), + listOf(0u, 2u) to Rational(181421, 315), + listOf(1u, 2u) to Rational(77813, 378), + listOf(2u, 2u) to Rational(598583, 7560), + listOf(3u, 2u) to Rational(85, 27), + listOf(4u, 2u) to Rational(2, 5), + listOf(0u, 3u) to Rational(130997, 315), + listOf(1u, 3u) to Rational(1093, 420), + listOf(2u, 3u) to Rational(9551, 2520), + listOf(3u, 3u) to Rational(-14, 45), + listOf(4u, 3u) to Rational(22, 45), + listOf(0u, 4u) to Rational(-2801, 9), + listOf(1u, 4u) to Rational(4033, 90), + listOf(2u, 4u) to Rational(6429, 80), + listOf(3u, 4u) to Rational(2851, 90), + listOf(4u, 4u) to Rational(293, 45), + listOf(0u, 5u) to Rational(-220, 1), + listOf(1u, 5u) to Rational(127, 1), + listOf(2u, 5u) to Rational(202, 5), + listOf(3u, 5u) to Rational(-63, 5), + listOf(4u, 5u) to Rational(-12, 5), + listOf(0u, 6u) to Rational(100, 1), + listOf(1u, 6u) to Rational(-80, 1), + listOf(2u, 6u) to Rational(-24, 1), + listOf(3u, 6u) to Rational(16, 1), + listOf(4u, 6u) to Rational(4, 1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(5407, 9), + listOf(1u) to Rational(9568, 27), + listOf(2u) to Rational(4996, 27), + listOf(3u) to Rational(352, 9), + listOf(4u) to Rational(22, 3), + listOf(0u, 1u) to Rational(104411, 126), + listOf(1u, 1u) to Rational(6001, 126), + listOf(2u, 1u) to Rational(-796, 21), + listOf(3u, 1u) to Rational(-5389, 126), + listOf(4u, 1u) to Rational(-166, 21), + listOf(0u, 2u) to Rational(-35327, 126), + listOf(1u, 2u) to Rational(53, 252), + listOf(2u, 2u) to Rational(849197, 6048), + listOf(3u, 2u) to Rational(22361, 252), + listOf(4u, 2u) to Rational(773, 42), + listOf(0u, 3u) to Rational(-6067, 21), + listOf(1u, 3u) to Rational(39049, 126), + listOf(2u, 3u) to Rational(80303, 1008), + listOf(3u, 3u) to Rational(-3035, 63), + listOf(4u, 3u) to Rational(-209, 21), + listOf(0u, 4u) to Rational(3113, 21), + listOf(1u, 4u) to Rational(-22345, 126), + listOf(2u, 4u) to Rational(-30931, 1008), + listOf(3u, 4u) to Rational(5837, 126), + listOf(4u, 4u) to Rational(229, 21), + listOf(0u, 5u) to Rational(-2120, 21), + listOf(1u, 5u) to Rational(451, 7), + listOf(2u, 5u) to Rational(422, 21), + listOf(3u, 5u) to Rational(-181, 21), + listOf(4u, 5u) to Rational(-40, 21), + listOf(0u, 6u) to Rational(100, 3), + listOf(1u, 6u) to Rational(-80, 3), + listOf(2u, 6u) to Rational(-8, 1), + listOf(3u, 6u) to Rational(16, 3), + listOf(4u, 6u) to Rational(4, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, bufferOf( + NumberedPolynomialAsIs( + listOf() to Rational(18, 1), + listOf(1u) to Rational(16, 3), + listOf(2u) to Rational(12, 6), + listOf(0u, 1u) to Rational(13, 1), + listOf(1u, 1u) to Rational(-11, 4), + listOf(2u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(-10, 1), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(2, 1), + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 6), + listOf(1u) to Rational(1, 6), + listOf(2u) to Rational(-2, 9), + listOf(0u, 1u) to Rational(15, 1), + listOf(1u, 1u) to Rational(18, 7), + listOf(2u, 1u) to Rational(2, 5), + listOf(0u, 2u) to Rational(12, 9), + listOf(1u, 2u) to Rational(-3, 5), + listOf(2u, 2u) to Rational(4, 4), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-11, 9), + listOf(1u) to Rational(4, 9), + listOf(2u) to Rational(11, 6), + listOf(0u, 1u) to Rational(-5, 6), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(-1, 7), + listOf(0u, 2u) to Rational(9, 1), + listOf(1u, 2u) to Rational(6, 7), + listOf(2u, 2u) to Rational(1, 3), + ) + ).substitute(RationalField, bufferOf>()), + "test 6" + ) + } + @Test + @Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not. + // Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction_Buffer() { + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(0) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ) + )), + "test 1" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(4u) to Rational(-17166109, 793800), + listOf(3u, 1u) to Rational(-930960143, 5556600), + listOf(2u, 2u) to Rational(-144665109691, 350065800), + listOf(1u, 3u) to Rational(-17232577, 52920), + listOf(0u, 4u) to Rational(-68141, 1323), + ), + NumberedPolynomialAsIs( + listOf(4u) to Rational(-57522533, 14288400), + listOf(3u, 1u) to Rational(-13085162953, 300056400), + listOf(2u, 2u) to Rational(-92093367341, 525098700), + listOf(1u, 3u) to Rational(-1979342797, 6667920), + listOf(0u, 4u) to Rational(-3082727, 21168), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(11, 5), + listOf(0u, 1u) to Rational(8, 4), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(1, 9), + listOf(0u, 1u) to Rational(11, 7), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf(1u) to Rational(-2, 7), + listOf(0u, 1u) to Rational(-4, 3), + ), + NumberedPolynomialAsIs( + listOf(1u) to Rational(3, 6), + listOf(0u, 1u) to Rational(12, 8), + ) + ), + )), + "test 2" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-130778291, 76800), + listOf(1u) to Rational(-445270919, 230400), + listOf(2u) to Rational(44578444937, 14515200), + listOf(3u) to Rational(17329402153, 1555200), + listOf(4u) to Rational(89239926809, 2332800), + listOf(5u) to Rational(2808812267, 145152), + listOf(6u) to Rational(-21362661007, 725760), + listOf(7u) to Rational(-258455443, 2016), + listOf(8u) to Rational(-21454693, 96), + listOf(0u, 1u) to Rational(-1002137, 15360), + listOf(1u, 1u) to Rational(-1704849697, 430080), + listOf(2u, 1u) to Rational(-57657676789, 4838400), + listOf(3u, 1u) to Rational(-101331731, 89600), + listOf(4u, 1u) to Rational(5362280079329, 130636800), + listOf(5u, 1u) to Rational(4069896167053, 130636800), + listOf(6u, 1u) to Rational(12011514569, 544320), + listOf(7u, 1u) to Rational(138293195623, 725760), + listOf(8u, 1u) to Rational(6228779419, 48384), + listOf(0u, 2u) to Rational(-32395872823, 8064000), + listOf(1u, 2u) to Rational(-7398505523, 2304000), + listOf(2u, 2u) to Rational(95217051699521, 3048192000), + listOf(3u, 2u) to Rational(198026968812079, 3657830400), + listOf(4u, 2u) to Rational(4291645618499, 228614400), + listOf(5u, 2u) to Rational(-33211690942439, 914457600), + listOf(6u, 2u) to Rational(-637385538163153, 1371686400), + listOf(7u, 2u) to Rational(-138671528276273, 182891520), + listOf(8u, 2u) to Rational(-14566368751, 217728), + listOf(0u, 3u) to Rational(-10538718719, 2016000), + listOf(1u, 3u) to Rational(-1844485375199, 84672000), + listOf(2u, 3u) to Rational(103968665891, 12096000), + listOf(3u, 3u) to Rational(175402107278351, 1828915200), + listOf(4u, 3u) to Rational(8020699588879, 114307200), + listOf(5u, 3u) to Rational(3414841894991, 38102400), + listOf(6u, 3u) to Rational(1848405591611, 4665600), + listOf(7u, 3u) to Rational(39486708738989, 137168640), + listOf(8u, 3u) to Rational(255926289517, 9144576), + listOf(0u, 4u) to Rational(-655379564629, 105840000), + listOf(1u, 4u) to Rational(-208336039441, 127008000), + listOf(2u, 4u) to Rational(40173146771411, 1143072000), + listOf(3u, 4u) to Rational(150473493581239, 2667168000), + listOf(4u, 4u) to Rational(38833783990483, 1143072000), + listOf(5u, 4u) to Rational(-1963676248203053, 4800902400), + listOf(6u, 4u) to Rational(-2598759412825747, 3200601600), + listOf(7u, 4u) to Rational(-192895352019667, 1280240640), + listOf(8u, 4u) to Rational(3737382679, 6858432), + listOf(0u, 5u) to Rational(-16959378721, 1890000), + listOf(1u, 5u) to Rational(-1864802244743, 79380000), + listOf(2u, 5u) to Rational(13449261536489, 666792000), + listOf(3u, 5u) to Rational(215272234137329, 2667168000), + listOf(4u, 5u) to Rational(6040691379277, 83349000), + listOf(5u, 5u) to Rational(153687143525887, 800150400), + listOf(6u, 5u) to Rational(475602854903563, 2400451200), + listOf(7u, 5u) to Rational(27315599358749, 640120320), + listOf(8u, 5u) to Rational(-2630413357, 10668672), + listOf(0u, 6u) to Rational(-6654999511, 2646000), + listOf(1u, 6u) to Rational(-67885252327, 15876000), + listOf(2u, 6u) to Rational(5786776220983, 2667168000), + listOf(3u, 6u) to Rational(60615922629083, 1143072000), + listOf(4u, 6u) to Rational(-34703539637627407, 672126336000), + listOf(5u, 6u) to Rational(-744694192134101, 2240421120), + listOf(6u, 6u) to Rational(-1782470617231, 14817600), + listOf(7u, 6u) to Rational(59123208433, 8890560), + listOf(8u, 6u) to Rational(-141653, 5292), + listOf(0u, 7u) to Rational(-338051969, 441000), + listOf(1u, 7u) to Rational(468850013, 1764000), + listOf(2u, 7u) to Rational(2102343426101, 222264000), + listOf(3u, 7u) to Rational(7836130602007, 1333584000), + listOf(4u, 7u) to Rational(16239111865997, 746807040), + listOf(5u, 7u) to Rational(3824649185383, 88905600), + listOf(6u, 7u) to Rational(56058614459, 3457440), + listOf(7u, 7u) to Rational(-396766339, 493920), + listOf(8u, 7u) to Rational(-165147, 2744), + listOf(0u, 8u) to Rational(-3088619, 58800), + listOf(1u, 8u) to Rational(155343347, 88200), + listOf(2u, 8u) to Rational(100098736469, 7408800), + listOf(3u, 8u) to Rational(109725511381, 7408800), + listOf(4u, 8u) to Rational(-2431199641013, 59270400), + listOf(5u, 8u) to Rational(-102872383249, 3457440), + listOf(6u, 8u) to Rational(1449461309, 576240), + listOf(7u, 8u) to Rational(812775, 1372), + listOf(8u, 8u) to Rational(-16461, 343) + ), + NumberedPolynomialAsIs( + listOf() to Rational(164202773, 230400), + listOf(1u) to Rational(-70345303, 518400), + listOf(2u) to Rational(-4229702731, 4665600), + listOf(3u) to Rational(3262171027, 6998400), + listOf(4u) to Rational(-25423104169, 13996800), + listOf(5u) to Rational(64061869, 349920), + listOf(6u) to Rational(-1655878091, 116640), + listOf(7u) to Rational(-7991441, 648), + listOf(8u) to Rational(-502591, 18), + listOf(0u, 1u) to Rational(-8780429, 3840), + listOf(1u, 1u) to Rational(434272361, 115200), + listOf(2u, 1u) to Rational(429825727, 41472), + listOf(3u, 1u) to Rational(-10066790339, 6998400), + listOf(4u, 1u) to Rational(70022035471, 20995200), + listOf(5u, 1u) to Rational(-32070283493, 1399680), + listOf(6u, 1u) to Rational(-22051101001, 1399680), + listOf(7u, 1u) to Rational(-126493427, 12960), + listOf(8u, 1u) to Rational(3050245, 864), + listOf(0u, 2u) to Rational(-1194654631, 345600), + listOf(1u, 2u) to Rational(-542961452671, 31104000), + listOf(2u, 2u) to Rational(-234000873607, 48988800), + listOf(3u, 2u) to Rational(140520538087, 3628800), + listOf(4u, 2u) to Rational(9215088876563, 130636800), + listOf(5u, 2u) to Rational(27590569647253, 293932800), + listOf(6u, 2u) to Rational(5129057792891, 97977600), + listOf(7u, 2u) to Rational(-106334191, 5103), + listOf(8u, 2u) to Rational(-1024113911, 435456), + listOf(0u, 3u) to Rational(76223843, 6000), + listOf(1u, 3u) to Rational(57425857357, 2592000), + listOf(2u, 3u) to Rational(-2044736497573, 46656000), + listOf(3u, 3u) to Rational(-26155810120031, 293932800), + listOf(4u, 3u) to Rational(-1064419459813, 6998400), + listOf(5u, 3u) to Rational(-753782018389, 4082400), + listOf(6u, 3u) to Rational(-291973360873, 2799360), + listOf(7u, 3u) to Rational(-46372122599, 816480), + listOf(8u, 3u) to Rational(3579859657, 653184), + listOf(0u, 4u) to Rational(-13374241901, 4320000), + listOf(1u, 4u) to Rational(306606499811, 54432000), + listOf(2u, 4u) to Rational(964267124745437, 13716864000), + listOf(3u, 4u) to Rational(21603809415373, 182891520), + listOf(4u, 4u) to Rational(1097860214654027, 6858432000), + listOf(5u, 4u) to Rational(161615254570669, 914457600), + listOf(6u, 4u) to Rational(758415239461, 22861440), + listOf(7u, 4u) to Rational(2585568355471, 274337280), + listOf(8u, 4u) to Rational(-70433747863, 9144576), + listOf(0u, 5u) to Rational(-9582586217, 2520000), + listOf(1u, 5u) to Rational(-19093471394171, 635040000), + listOf(2u, 5u) to Rational(-13010261944411, 381024000), + listOf(3u, 5u) to Rational(-259039825301861, 4572288000), + listOf(4u, 5u) to Rational(-305081119071079, 2286144000), + listOf(5u, 5u) to Rational(-1923114383311, 19595520), + listOf(6u, 5u) to Rational(-14181787253231, 228614400), + listOf(7u, 5u) to Rational(-3959584789, 4354560), + listOf(8u, 5u) to Rational(4691742523, 762048), + listOf(0u, 6u) to Rational(-588323437, 180000), + listOf(1u, 6u) to Rational(5952234691, 52920000), + listOf(2u, 6u) to Rational(21001851056959, 1088640000), + listOf(3u, 6u) to Rational(84668034357563, 2133734400), + listOf(4u, 6u) to Rational(2029754605811557, 25604812800), + listOf(5u, 6u) to Rational(11721216739823, 426746880), + listOf(6u, 6u) to Rational(-8275903187003, 2133734400), + listOf(7u, 6u) to Rational(-4730447299, 2540160), + listOf(8u, 6u) to Rational(-46069985, 21168), + listOf(0u, 7u) to Rational(-75711301, 117600), + listOf(1u, 7u) to Rational(32430417413, 7056000), + listOf(2u, 7u) to Rational(677988533153, 98784000), + listOf(3u, 7u) to Rational(-948417645827, 71124480), + listOf(4u, 7u) to Rational(-11320265215207, 711244800), + listOf(5u, 7u) to Rational(-676438627783, 50803200), + listOf(6u, 7u) to Rational(-7382274253, 1975680), + listOf(7u, 7u) to Rational(6505733, 2205), + listOf(8u, 7u) to Rational(450137, 882), + listOf(0u, 8u) to Rational(-8368253, 78400), + listOf(1u, 8u) to Rational(6833783, 117600), + listOf(2u, 8u) to Rational(4528971133, 5927040), + listOf(3u, 8u) to Rational(146252636617, 29635200), + listOf(4u, 8u) to Rational(8321882556889, 1659571200), + listOf(5u, 8u) to Rational(-4686033011, 1975680), + listOf(6u, 8u) to Rational(-1074445963, 987840), + listOf(7u, 8u) to Rational(-142313, 588), + listOf(8u, 8u) to Rational(-4281, 49) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(5, 8), + listOf(1u) to Rational(-12, 6), + listOf(2u) to Rational(7, 6), + listOf(0u, 1u) to Rational(-10, 4), + listOf(1u, 1u) to Rational(-7, 6), + listOf(2u, 1u) to Rational(8, 9), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-13, 4), + listOf(2u, 2u) to Rational(5, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(10, 6), + listOf(1u) to Rational(-18, 6), + listOf(2u) to Rational(5, 1), + listOf(0u, 1u) to Rational(17, 7), + listOf(1u, 1u) to Rational(8, 4), + listOf(2u, 1u) to Rational(-4, 9), + listOf(0u, 2u) to Rational(-6, 5), + listOf(1u, 2u) to Rational(-15, 8), + listOf(2u, 2u) to Rational(-18, 5), + ) + ), + )), + "test 3" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-130778291, 76800), + listOf(1u) to Rational(-445270919, 230400), + listOf(2u) to Rational(44578444937, 14515200), + listOf(3u) to Rational(17329402153, 1555200), + listOf(4u) to Rational(89239926809, 2332800), + listOf(5u) to Rational(2808812267, 145152), + listOf(6u) to Rational(-21362661007, 725760), + listOf(7u) to Rational(-258455443, 2016), + listOf(8u) to Rational(-21454693, 96), + listOf(0u, 1u) to Rational(-1002137, 15360), + listOf(1u, 1u) to Rational(-1704849697, 430080), + listOf(2u, 1u) to Rational(-57657676789, 4838400), + listOf(3u, 1u) to Rational(-101331731, 89600), + listOf(4u, 1u) to Rational(5362280079329, 130636800), + listOf(5u, 1u) to Rational(4069896167053, 130636800), + listOf(6u, 1u) to Rational(12011514569, 544320), + listOf(7u, 1u) to Rational(138293195623, 725760), + listOf(8u, 1u) to Rational(6228779419, 48384), + listOf(0u, 2u) to Rational(-32395872823, 8064000), + listOf(1u, 2u) to Rational(-7398505523, 2304000), + listOf(2u, 2u) to Rational(95217051699521, 3048192000), + listOf(3u, 2u) to Rational(198026968812079, 3657830400), + listOf(4u, 2u) to Rational(4291645618499, 228614400), + listOf(5u, 2u) to Rational(-33211690942439, 914457600), + listOf(6u, 2u) to Rational(-637385538163153, 1371686400), + listOf(7u, 2u) to Rational(-138671528276273, 182891520), + listOf(8u, 2u) to Rational(-14566368751, 217728), + listOf(0u, 3u) to Rational(-10538718719, 2016000), + listOf(1u, 3u) to Rational(-1844485375199, 84672000), + listOf(2u, 3u) to Rational(103968665891, 12096000), + listOf(3u, 3u) to Rational(175402107278351, 1828915200), + listOf(4u, 3u) to Rational(8020699588879, 114307200), + listOf(5u, 3u) to Rational(3414841894991, 38102400), + listOf(6u, 3u) to Rational(1848405591611, 4665600), + listOf(7u, 3u) to Rational(39486708738989, 137168640), + listOf(8u, 3u) to Rational(255926289517, 9144576), + listOf(0u, 4u) to Rational(-655379564629, 105840000), + listOf(1u, 4u) to Rational(-208336039441, 127008000), + listOf(2u, 4u) to Rational(40173146771411, 1143072000), + listOf(3u, 4u) to Rational(150473493581239, 2667168000), + listOf(4u, 4u) to Rational(38833783990483, 1143072000), + listOf(5u, 4u) to Rational(-1963676248203053, 4800902400), + listOf(6u, 4u) to Rational(-2598759412825747, 3200601600), + listOf(7u, 4u) to Rational(-192895352019667, 1280240640), + listOf(8u, 4u) to Rational(3737382679, 6858432), + listOf(0u, 5u) to Rational(-16959378721, 1890000), + listOf(1u, 5u) to Rational(-1864802244743, 79380000), + listOf(2u, 5u) to Rational(13449261536489, 666792000), + listOf(3u, 5u) to Rational(215272234137329, 2667168000), + listOf(4u, 5u) to Rational(6040691379277, 83349000), + listOf(5u, 5u) to Rational(153687143525887, 800150400), + listOf(6u, 5u) to Rational(475602854903563, 2400451200), + listOf(7u, 5u) to Rational(27315599358749, 640120320), + listOf(8u, 5u) to Rational(-2630413357, 10668672), + listOf(0u, 6u) to Rational(-6654999511, 2646000), + listOf(1u, 6u) to Rational(-67885252327, 15876000), + listOf(2u, 6u) to Rational(5786776220983, 2667168000), + listOf(3u, 6u) to Rational(60615922629083, 1143072000), + listOf(4u, 6u) to Rational(-34703539637627407, 672126336000), + listOf(5u, 6u) to Rational(-744694192134101, 2240421120), + listOf(6u, 6u) to Rational(-1782470617231, 14817600), + listOf(7u, 6u) to Rational(59123208433, 8890560), + listOf(8u, 6u) to Rational(-141653, 5292), + listOf(0u, 7u) to Rational(-338051969, 441000), + listOf(1u, 7u) to Rational(468850013, 1764000), + listOf(2u, 7u) to Rational(2102343426101, 222264000), + listOf(3u, 7u) to Rational(7836130602007, 1333584000), + listOf(4u, 7u) to Rational(16239111865997, 746807040), + listOf(5u, 7u) to Rational(3824649185383, 88905600), + listOf(6u, 7u) to Rational(56058614459, 3457440), + listOf(7u, 7u) to Rational(-396766339, 493920), + listOf(8u, 7u) to Rational(-165147, 2744), + listOf(0u, 8u) to Rational(-3088619, 58800), + listOf(1u, 8u) to Rational(155343347, 88200), + listOf(2u, 8u) to Rational(100098736469, 7408800), + listOf(3u, 8u) to Rational(109725511381, 7408800), + listOf(4u, 8u) to Rational(-2431199641013, 59270400), + listOf(5u, 8u) to Rational(-102872383249, 3457440), + listOf(6u, 8u) to Rational(1449461309, 576240), + listOf(7u, 8u) to Rational(812775, 1372), + listOf(8u, 8u) to Rational(-16461, 343) + ), + NumberedPolynomialAsIs( + listOf() to Rational(164202773, 230400), + listOf(1u) to Rational(-70345303, 518400), + listOf(2u) to Rational(-4229702731, 4665600), + listOf(3u) to Rational(3262171027, 6998400), + listOf(4u) to Rational(-25423104169, 13996800), + listOf(5u) to Rational(64061869, 349920), + listOf(6u) to Rational(-1655878091, 116640), + listOf(7u) to Rational(-7991441, 648), + listOf(8u) to Rational(-502591, 18), + listOf(0u, 1u) to Rational(-8780429, 3840), + listOf(1u, 1u) to Rational(434272361, 115200), + listOf(2u, 1u) to Rational(429825727, 41472), + listOf(3u, 1u) to Rational(-10066790339, 6998400), + listOf(4u, 1u) to Rational(70022035471, 20995200), + listOf(5u, 1u) to Rational(-32070283493, 1399680), + listOf(6u, 1u) to Rational(-22051101001, 1399680), + listOf(7u, 1u) to Rational(-126493427, 12960), + listOf(8u, 1u) to Rational(3050245, 864), + listOf(0u, 2u) to Rational(-1194654631, 345600), + listOf(1u, 2u) to Rational(-542961452671, 31104000), + listOf(2u, 2u) to Rational(-234000873607, 48988800), + listOf(3u, 2u) to Rational(140520538087, 3628800), + listOf(4u, 2u) to Rational(9215088876563, 130636800), + listOf(5u, 2u) to Rational(27590569647253, 293932800), + listOf(6u, 2u) to Rational(5129057792891, 97977600), + listOf(7u, 2u) to Rational(-106334191, 5103), + listOf(8u, 2u) to Rational(-1024113911, 435456), + listOf(0u, 3u) to Rational(76223843, 6000), + listOf(1u, 3u) to Rational(57425857357, 2592000), + listOf(2u, 3u) to Rational(-2044736497573, 46656000), + listOf(3u, 3u) to Rational(-26155810120031, 293932800), + listOf(4u, 3u) to Rational(-1064419459813, 6998400), + listOf(5u, 3u) to Rational(-753782018389, 4082400), + listOf(6u, 3u) to Rational(-291973360873, 2799360), + listOf(7u, 3u) to Rational(-46372122599, 816480), + listOf(8u, 3u) to Rational(3579859657, 653184), + listOf(0u, 4u) to Rational(-13374241901, 4320000), + listOf(1u, 4u) to Rational(306606499811, 54432000), + listOf(2u, 4u) to Rational(964267124745437, 13716864000), + listOf(3u, 4u) to Rational(21603809415373, 182891520), + listOf(4u, 4u) to Rational(1097860214654027, 6858432000), + listOf(5u, 4u) to Rational(161615254570669, 914457600), + listOf(6u, 4u) to Rational(758415239461, 22861440), + listOf(7u, 4u) to Rational(2585568355471, 274337280), + listOf(8u, 4u) to Rational(-70433747863, 9144576), + listOf(0u, 5u) to Rational(-9582586217, 2520000), + listOf(1u, 5u) to Rational(-19093471394171, 635040000), + listOf(2u, 5u) to Rational(-13010261944411, 381024000), + listOf(3u, 5u) to Rational(-259039825301861, 4572288000), + listOf(4u, 5u) to Rational(-305081119071079, 2286144000), + listOf(5u, 5u) to Rational(-1923114383311, 19595520), + listOf(6u, 5u) to Rational(-14181787253231, 228614400), + listOf(7u, 5u) to Rational(-3959584789, 4354560), + listOf(8u, 5u) to Rational(4691742523, 762048), + listOf(0u, 6u) to Rational(-588323437, 180000), + listOf(1u, 6u) to Rational(5952234691, 52920000), + listOf(2u, 6u) to Rational(21001851056959, 1088640000), + listOf(3u, 6u) to Rational(84668034357563, 2133734400), + listOf(4u, 6u) to Rational(2029754605811557, 25604812800), + listOf(5u, 6u) to Rational(11721216739823, 426746880), + listOf(6u, 6u) to Rational(-8275903187003, 2133734400), + listOf(7u, 6u) to Rational(-4730447299, 2540160), + listOf(8u, 6u) to Rational(-46069985, 21168), + listOf(0u, 7u) to Rational(-75711301, 117600), + listOf(1u, 7u) to Rational(32430417413, 7056000), + listOf(2u, 7u) to Rational(677988533153, 98784000), + listOf(3u, 7u) to Rational(-948417645827, 71124480), + listOf(4u, 7u) to Rational(-11320265215207, 711244800), + listOf(5u, 7u) to Rational(-676438627783, 50803200), + listOf(6u, 7u) to Rational(-7382274253, 1975680), + listOf(7u, 7u) to Rational(6505733, 2205), + listOf(8u, 7u) to Rational(450137, 882), + listOf(0u, 8u) to Rational(-8368253, 78400), + listOf(1u, 8u) to Rational(6833783, 117600), + listOf(2u, 8u) to Rational(4528971133, 5927040), + listOf(3u, 8u) to Rational(146252636617, 29635200), + listOf(4u, 8u) to Rational(8321882556889, 1659571200), + listOf(5u, 8u) to Rational(-4686033011, 1975680), + listOf(6u, 8u) to Rational(-1074445963, 987840), + listOf(7u, 8u) to Rational(-142313, 588), + listOf(8u, 8u) to Rational(-4281, 49) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(14, 4), + listOf(1u) to Rational(7, 6), + listOf(2u) to Rational(7, 2), + listOf(0u, 1u) to Rational(-15, 2), + listOf(1u, 1u) to Rational(-13, 8), + listOf(2u, 1u) to Rational(-14, 3), + listOf(0u, 2u) to Rational(-7, 6), + listOf(1u, 2u) to Rational(7, 4), + listOf(2u, 2u) to Rational(9, 7), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-7, 4), + listOf(1u) to Rational(-6, 3), + listOf(2u) to Rational(-16, 2), + listOf(0u, 1u) to Rational(-15, 5), + listOf(1u, 1u) to Rational(4, 6), + listOf(2u, 1u) to Rational(5, 4), + listOf(0u, 2u) to Rational(-12, 5), + listOf(1u, 2u) to Rational(-18, 2), + listOf(2u, 2u) to Rational(6, 7), + ) + ), + )), + "test 4" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-506213, 2800), + listOf(1u) to Rational(9859, 315), + listOf(2u) to Rational(17384377, 11340), + listOf(3u) to Rational(-9662, 63), + listOf(4u) to Rational(-12563, 4), + listOf(0u, 1u) to Rational(-486293, 22400), + listOf(1u, 1u) to Rational(-6530947, 25200), + listOf(2u, 1u) to Rational(866125, 18144), + listOf(3u, 1u) to Rational(2948747, 2520), + listOf(4u, 1u) to Rational(1196611, 2016), + listOf(0u, 2u) to Rational(-20266021, 117600), + listOf(1u, 2u) to Rational(26656339, 44100), + listOf(2u, 2u) to Rational(19499183, 18144), + listOf(3u, 2u) to Rational(-19801849, 7560), + listOf(4u, 2u) to Rational(-2639635, 1296), + listOf(0u, 3u) to Rational(-5017697, 29400), + listOf(1u, 3u) to Rational(-606007, 1575), + listOf(2u, 3u) to Rational(127494487, 132300), + listOf(3u, 3u) to Rational(166567, 105), + listOf(4u, 3u) to Rational(486403, 18144), + listOf(0u, 4u) to Rational(-32182, 735), + listOf(1u, 4u) to Rational(2420671, 8820), + listOf(2u, 4u) to Rational(-12619193, 26460), + listOf(3u, 4u) to Rational(-6823067, 5670), + listOf(4u, 4u) to Rational(-2311693, 13608), + listOf(0u, 5u) to Rational(-13324, 245), + listOf(1u, 5u) to Rational(1966, 35), + listOf(2u, 5u) to Rational(1052719, 2520), + listOf(3u, 5u) to Rational(19153, 270), + listOf(4u, 5u) to Rational(701, 54), + listOf(0u, 6u) to Rational(4647, 196), + listOf(1u, 6u) to Rational(2197, 28), + listOf(2u, 6u) to Rational(-43853, 336), + listOf(3u, 6u) to Rational(-301, 3), + listOf(4u, 6u) to Rational(34, 3) + ), + NumberedPolynomialAsIs( + listOf() to Rational(-2843, 1600), + listOf(1u) to Rational(-1483, 240), + listOf(2u) to Rational(110623, 1296), + listOf(3u) to Rational(1265, 72), + listOf(4u) to Rational(-5011, 16), + listOf(0u, 1u) to Rational(47743, 1800), + listOf(1u, 1u) to Rational(619229, 32400), + listOf(2u, 1u) to Rational(-5978369, 58320), + listOf(3u, 1u) to Rational(-86081, 1620), + listOf(4u, 1u) to Rational(6325, 72), + listOf(0u, 2u) to Rational(110951, 3360), + listOf(1u, 2u) to Rational(-9550649, 302400), + listOf(2u, 2u) to Rational(6542933, 85050), + listOf(3u, 2u) to Rational(4708291, 38880), + listOf(4u, 2u) to Rational(-433327, 1296), + listOf(0u, 3u) to Rational(56143, 600), + listOf(1u, 3u) to Rational(94243, 720), + listOf(2u, 3u) to Rational(-46779139, 226800), + listOf(3u, 3u) to Rational(-6948253, 12960), + listOf(4u, 3u) to Rational(-260261, 486), + listOf(0u, 4u) to Rational(-3205317, 19600), + listOf(1u, 4u) to Rational(-201253, 1050), + listOf(2u, 4u) to Rational(332192677, 302400), + listOf(3u, 4u) to Rational(351511, 360), + listOf(4u, 4u) to Rational(-40547, 81), + listOf(0u, 5u) to Rational(-65421, 1960), + listOf(1u, 5u) to Rational(-10118, 35), + listOf(2u, 5u) to Rational(-4341709, 10080), + listOf(3u, 5u) to Rational(-91703, 360), + listOf(4u, 5u) to Rational(-85, 9), + listOf(0u, 6u) to Rational(-25965, 784), + listOf(1u, 6u) to Rational(3351, 16), + listOf(2u, 6u) to Rational(595159, 1344), + listOf(3u, 6u) to Rational(-1381, 12), + listOf(4u, 6u) to Rational(-155, 3) + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, bufferOf( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-17, 5), + listOf(1u) to Rational(2, 6), + listOf(2u) to Rational(14, 1), + listOf(0u, 1u) to Rational(-6, 6), + listOf(1u, 1u) to Rational(-7, 3), + listOf(2u, 1u) to Rational(-2, 9), + listOf(0u, 2u) to Rational(-9, 6), + listOf(1u, 2u) to Rational(17, 4), + listOf(2u, 2u) to Rational(2, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(5, 4), + listOf(1u) to Rational(-5, 9), + listOf(2u) to Rational(-3, 6), + listOf(0u, 1u) to Rational(6, 5), + listOf(1u, 1u) to Rational(14, 5), + listOf(2u, 1u) to Rational(5, 2), + listOf(0u, 2u) to Rational(-18, 7), + listOf(1u, 2u) to Rational(-8, 2), + listOf(2u, 2u) to Rational(18, 9), + ) + ), + )), + "test 5" + ) + assertEquals( + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(10, 2), + listOf(1u) to Rational(6, 7), + listOf(2u) to Rational(-16, 1), + listOf(0u, 1u) to Rational(13, 8), + listOf(1u, 1u) to Rational(-12, 1), + listOf(2u, 1u) to Rational(16, 8), + listOf(0u, 2u) to Rational(10, 4), + listOf(1u, 2u) to Rational(4, 1), + listOf(2u, 2u) to Rational(-11, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1, 4), + listOf(1u) to Rational(-17, 4), + listOf(2u) to Rational(-14, 8), + listOf(0u, 1u) to Rational(17, 9), + listOf(1u, 1u) to Rational(1, 3), + listOf(2u, 1u) to Rational(7, 6), + listOf(0u, 2u) to Rational(16, 3), + listOf(1u, 2u) to Rational(-17, 1), + listOf(2u, 2u) to Rational(-10, 8), + ) + ).substitute(RationalField, bufferOf>()), + "test 6" + ) + } + @Test + fun test_Polynomial_substituteFully_Double_Buffer() { + assertEquals( + 0.0, + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ).substituteFully(bufferOf( + 1.0 + )), + 0.001, + "test 1" + ) + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 2" + ) { + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf()) + } + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 3" + ) { + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf( + 0.0, + )) + } + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 4" + ) { + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf( + 0.4846192734143442, + )) + } + assertEquals( + 1.934530767358133, + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + )), + 0.001, + "test 5" + ) + assertEquals( + 1.934530767358133, + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + 0.9211194782050933 + )), + 0.001, + "test 6" + ) + assertEquals( + 1.934530767358133, + NumberedPolynomialAsIs( + listOf() to 0.8597048543814783, + listOf(1u) to 0.22997637465889875, + listOf(2u) to 0.32675302591924016, + listOf(0u, 1u) to 0.4561746111587508, + listOf(1u, 1u) to 0.5304946210170756, + listOf(2u, 1u) to 0.6244313712888998, + listOf(0u, 2u) to 0.2700930201481795, + listOf(1u, 2u) to -0.06962351375204712, + listOf(2u, 2u) to -0.015206988092131501, + ).substituteFully(bufferOf( + 0.4846192734143442, + 0.8400458576651112, + 0.9211194782050933, + 0.4752854632152105 + )), + 0.001, + "test 7" + ) + } + @Test + fun test_Polynomial_substituteFully_Constant_Buffer() { + assertEquals( + Rational(0), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ).substituteFully(RationalField, bufferOf( + Rational(1) + )), + "test 1" + ) + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 2" + ) { + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substituteFully(RationalField, bufferOf()) + } + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 3" + ) { + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substituteFully( + RationalField, bufferOf( + Rational(-2, 5), + ) + ) + } + // https://www.wolframalpha.com/input?i=%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2+where+x+%3D+-2%2F5%2C+y+%3D+12%2F9 + assertEquals( + Rational(143, 150), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substituteFully(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + )), + "test 4" + ) + assertEquals( + Rational(143, 150), + NumberedPolynomialAsIs( + listOf() to Rational(-3, 2), + listOf(1u) to Rational(8, 6), + listOf(2u) to Rational(14, 6), + listOf(0u, 1u) to Rational(-3, 1), + listOf(1u, 1u) to Rational(-19, 2), + listOf(2u, 1u) to Rational(9, 4), + listOf(0u, 2u) to Rational(5, 5), + listOf(1u, 2u) to Rational(18, 9), + listOf(2u, 2u) to Rational(5, 2), + ).substituteFully(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + Rational(57, 179), + )), + "test 5" + ) + // https://www.wolframalpha.com/input?i=%28%28-3%2F2+%2B+8%2F6+x+%2B+14%2F6+x%5E2%29+%2B+%28-3%2F1+%2B+-19%2F2+x+%2B+9%2F4+x%5E2%29+y+%2B+%285%2F5+%2B+18%2F9+x+%2B+5%2F2+x%5E2%29+y%5E2%29+p%5E8+where+x+%3D+q%2Fp%2C+y+%3D+x%5E3%2C+p+%3D+-2%2F5%2C+q+%3D+12%2F9 + assertEquals( + Rational(47639065216, 2562890625), + NumberedPolynomialAsIs( + listOf(8u) to Rational(-3, 2), + listOf(7u, 1u) to Rational(8, 6), + listOf(6u, 2u) to Rational(14, 6), + listOf(5u, 3u) to Rational(-3, 1), + listOf(4u, 4u) to Rational(-19, 2), + listOf(3u, 5u) to Rational(9, 4), + listOf(2u, 6u) to Rational(5, 5), + listOf(1u, 7u) to Rational(18, 9), + listOf(0u, 8u) to Rational(5, 2), + ).substituteFully(RationalField, bufferOf( + Rational(-2, 5), + Rational(12, 9), + )), + "test 6" + ) + } + @Test + fun test_RationalFunction_substituteFully_Double_Buffer() { + assertEquals( + 0.0, + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 1.0, + listOf(1u) to -2.0, + listOf(2u) to 1.0, + ), + NumberedPolynomialAsIs( + listOf() to 1.0, + ) + ).substituteFully(bufferOf( + 1.0 + )), + 0.001, + "test 1" + ) + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 2" + ) { + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substituteFully(bufferOf()) + } + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 3" + ) { + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substituteFully( + bufferOf( + -8.11707689492641, + ) + ) + } + assertEquals( + -0.012718636022899672, + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substituteFully(bufferOf( + -8.11707689492641, + 0.795265651276015, + )), + 0.001, + "test 4" + ) + assertEquals( + -0.012718636022899672, + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to 6.593754860231304, + listOf(1u) to -7.853302571550634, + listOf(2u) to 1.2265042281530025, + listOf(0u, 1u) to 3.762648877294904, + listOf(1u, 1u) to -8.945144619305292, + listOf(2u, 1u) to -5.141384718042281, + listOf(0u, 2u) to 7.359794483988782, + listOf(1u, 2u) to -4.3526172680518815, + listOf(2u, 2u) to 0.907910924854372, + ), + NumberedPolynomialAsIs( + listOf() to 9.533292132172562, + listOf(1u) to -1.982814534018857, + listOf(2u) to -5.974248303415283, + listOf(0u, 1u) to 1.5876716499288879, + listOf(1u, 1u) to -7.535152566659664, + listOf(2u, 1u) to 0.7549300500153517, + listOf(0u, 2u) to -5.242030058021028, + listOf(1u, 2u) to -0.7265704289690582, + listOf(2u, 2u) to -7.139677818189821, + ) + ).substituteFully(bufferOf( + -8.11707689492641, + 0.795265651276015, + 0.9211194782050933 + )), + 0.001, + "test 5" + ) + } + @Test + fun test_RationalFunction_substituteFully_Constant_Buffer() { + assertEquals( + Rational(0), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1) + ), + NumberedPolynomialAsIs( + listOf() to Rational(1) + ) + ).substituteFully(RationalField, bufferOf( + Rational(1) + )), + "test 1" + ) + assertEquals( + Rational(-1322820, 2204953), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substituteFully(RationalField, bufferOf( + Rational(7, 5), + Rational(-13, 7), + Rational(-16, 4), + )), + "test 2" + ) + assertEquals( + Rational(-1322820, 2204953), + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substituteFully(RationalField, bufferOf( + Rational(7, 5), + Rational(-13, 7), + )), + "test 3" + ) + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 4" + ) { + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substituteFully( + RationalField, bufferOf( + Rational(7, 5), + ) + ) + } + assertFailsWithTypeAndMessage( + fullSubstitutionExceptionMessage, + "test 5" + ) { + NumberedRationalFunction( + NumberedPolynomialAsIs( + listOf() to Rational(-3, 5), + listOf(1u) to Rational(-18, 4), + listOf(2u) to Rational(9, 8), + listOf(0u, 1u) to Rational(-11, 6), + listOf(1u, 1u) to Rational(-16, 3), + listOf(2u, 1u) to Rational(12, 2), + listOf(0u, 2u) to Rational(5, 3), + listOf(1u, 2u) to Rational(17, 8), + listOf(2u, 2u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(11, 1), + listOf(1u) to Rational(4, 1), + listOf(2u) to Rational(-18, 3), + listOf(0u, 1u) to Rational(12, 9), + listOf(1u, 1u) to Rational(14, 7), + listOf(2u, 1u) to Rational(-17, 5), + listOf(0u, 2u) to Rational(-4, 1), + listOf(1u, 2u) to Rational(-5, 5), + listOf(2u, 2u) to Rational(-7, 8), + ) + ).substituteFully(RationalField, bufferOf()) + } + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_derivativeWithRespectTo_variable() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2), + listOf(1u) to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).derivativeWithRespectTo(RationalField, 0), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 3), + listOf(1u) to Rational(1, 1), + listOf(2u) to Rational(-33, 8), + listOf(3u) to Rational(72, 1), + listOf(0u, 1u) to Rational(2, 3), + listOf(1u, 1u) to Rational(-22, 1), + listOf(2u, 1u) to Rational(-1, 1), + listOf(3u, 1u) to Rational(-36, 1), + listOf(0u, 2u) to Rational(-8, 5), + listOf(1u, 2u) to Rational(-1, 4), + listOf(2u, 2u) to Rational(12, 7), + listOf(3u, 2u) to Rational(-2, 1), + listOf(0u, 3u) to Rational(16, 8), + listOf(1u, 3u) to Rational(-4, 1), + listOf(2u, 3u) to Rational(9, 2), + listOf(3u, 3u) to Rational(20, 9), + listOf(0u, 4u) to Rational(-10, 1), + listOf(1u, 4u) to Rational(-14, 1), + listOf(2u, 4u) to Rational(3, 7), + listOf(3u, 4u) to Rational(20, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, 0), + "test 2a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-18, 3), + listOf(1u) to Rational(2, 3), + listOf(2u) to Rational(-11, 1), + listOf(3u) to Rational(-1, 3), + listOf(4u) to Rational(-18, 2), + listOf(0u, 1u) to Rational(-20, 3), + listOf(1u, 1u) to Rational(-16, 5), + listOf(2u, 1u) to Rational(-1, 4), + listOf(3u, 1u) to Rational(8, 7), + listOf(4u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(9, 7), + listOf(1u, 2u) to Rational(6, 1), + listOf(2u, 2u) to Rational(-6, 1), + listOf(3u, 2u) to Rational(9, 2), + listOf(4u, 2u) to Rational(5, 3), + listOf(0u, 3u) to Rational(-9, 1), + listOf(1u, 3u) to Rational(-40, 1), + listOf(2u, 3u) to Rational(-28, 1), + listOf(3u, 3u) to Rational(4, 7), + listOf(4u, 3u) to Rational(20, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, 1), + "test 2b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(-1, 4), + listOf(2u, 2u) to Rational(12, 7), + listOf(3u, 2u) to Rational(-2, 1), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(-4, 1), + listOf(2u, 3u) to Rational(9, 2), + listOf(3u, 3u) to Rational(20, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(-14, 1), + listOf(2u, 4u) to Rational(3, 7), + listOf(3u, 4u) to Rational(20, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, 0), + "test 3a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(-1, 4), + listOf(3u, 1u) to Rational(8, 7), + listOf(4u, 1u) to Rational(-1, 1), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-6, 1), + listOf(3u, 2u) to Rational(9, 2), + listOf(4u, 2u) to Rational(5, 3), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-28, 1), + listOf(3u, 3u) to Rational(4, 7), + listOf(4u, 3u) to Rational(20, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, 1), + "test 3b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2, 3), + listOf(1u) to Rational(1, 1), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 1u) to Rational(2, 3), + listOf(1u, 1u) to Rational(-22, 1), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-8, 5), + listOf(1u, 2u) to Rational(-1, 4), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).derivativeWithRespectTo(RationalField, 0), + "test 4a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-18, 3), + listOf(1u) to Rational(2, 3), + listOf(2u) to Rational(-11, 1), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-20, 3), + listOf(1u, 1u) to Rational(-16, 5), + listOf(2u, 1u) to Rational(-1, 4), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).derivativeWithRespectTo(RationalField, 1), + "test 4b" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).derivativeWithRespectTo(RationalField, 5), + "test 5" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthDerivativeWithRespectTo_variable_order() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2), + listOf(1u) to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 0, 1u), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 0, 0u), + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 0, 2u), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 0, 3u), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 0, 4u), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 1, 0u), + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 1, 1u), + "test 7" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, 1, 2u), + "test 8" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1, 1), + listOf(1u) to Rational(-33, 4), + listOf(2u) to Rational(216, 1), + listOf(0u, 1u) to Rational(-22, 1), + listOf(1u, 1u) to Rational(-2, 1), + listOf(2u, 1u) to Rational(-108, 1), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(24, 7), + listOf(2u, 2u) to Rational(-6, 1), + listOf(0u, 3u) to Rational(-4, 1), + listOf(1u, 3u) to Rational(9, 1), + listOf(2u, 3u) to Rational(20, 3), + listOf(0u, 4u) to Rational(-14, 1), + listOf(1u, 4u) to Rational(6, 7), + listOf(2u, 4u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, 0, 2u), + "test 9a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-20, 3), + listOf(1u) to Rational(-16, 5), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(8, 7), + listOf(4u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(18, 7), + listOf(1u, 1u) to Rational(12, 1), + listOf(2u, 1u) to Rational(-12, 1), + listOf(3u, 1u) to Rational(9, 1), + listOf(4u, 1u) to Rational(10, 3), + listOf(0u, 2u) to Rational(-27, 1), + listOf(1u, 2u) to Rational(-120, 1), + listOf(2u, 2u) to Rational(-84, 1), + listOf(3u, 2u) to Rational(12, 7), + listOf(4u, 2u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, 1, 2u), + "test 9b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(24, 7), + listOf(2u, 2u) to Rational(-6, 1), + listOf(0u, 3u) to Rational(-4, 1), + listOf(1u, 3u) to Rational(9, 1), + listOf(2u, 3u) to Rational(20, 3), + listOf(0u, 4u) to Rational(-14, 1), + listOf(1u, 4u) to Rational(6, 7), + listOf(2u, 4u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, 0, 2u), + "test 10a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(8, 7), + listOf(4u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(-12, 1), + listOf(3u, 1u) to Rational(9, 1), + listOf(4u, 1u) to Rational(10, 3), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-84, 1), + listOf(3u, 2u) to Rational(12, 7), + listOf(4u, 2u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, 1, 2u), + "test 10b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1, 1), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(-22, 1), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, 0, 2u), + "test 11a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-20, 3), + listOf(1u) to Rational(-16, 5), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, 1, 2u), + "test 11b" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthDerivativeWithRespectTo_variablesAndOrders() { + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2), + listOf(1u) to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 1u)), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 0u)), + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 3u)), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 4u)), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 0u)), + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 1u)), + "test 7" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 8" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf()), + "test 9" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-2), + listOf(1u) to Rational(2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf( + 0 to 1u, + 1 to 0u + )), + "test 10" + ) + assertEquals( + NumberedPolynomialAsIs(), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthDerivativeWithRespectTo(RationalField, mapOf( + 0 to 0u, + 1 to 1u + )), + "test 11" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1, 1), + listOf(1u) to Rational(-33, 4), + listOf(2u) to Rational(216, 1), + listOf(0u, 1u) to Rational(-22, 1), + listOf(1u, 1u) to Rational(-2, 1), + listOf(2u, 1u) to Rational(-108, 1), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(24, 7), + listOf(2u, 2u) to Rational(-6, 1), + listOf(0u, 3u) to Rational(-4, 1), + listOf(1u, 3u) to Rational(9, 1), + listOf(2u, 3u) to Rational(20, 3), + listOf(0u, 4u) to Rational(-14, 1), + listOf(1u, 4u) to Rational(6, 7), + listOf(2u, 4u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 12a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(2, 3), + listOf(1u) to Rational(-22, 1), + listOf(2u) to Rational(-1, 1), + listOf(3u) to Rational(-36, 1), + listOf(0u, 1u) to Rational(-16, 5), + listOf(1u, 1u) to Rational(-1, 2), + listOf(2u, 1u) to Rational(24, 7), + listOf(3u, 1u) to Rational(-4, 1), + listOf(0u, 2u) to Rational(6, 1), + listOf(1u, 2u) to Rational(-12, 1), + listOf(2u, 2u) to Rational(27, 2), + listOf(3u, 2u) to Rational(20, 3), + listOf(0u, 3u) to Rational(-40, 1), + listOf(1u, 3u) to Rational(-56, 1), + listOf(2u, 3u) to Rational(12, 7), + listOf(3u, 3u) to Rational(80, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 12b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-20, 3), + listOf(1u) to Rational(-16, 5), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(8, 7), + listOf(4u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(18, 7), + listOf(1u, 1u) to Rational(12, 1), + listOf(2u, 1u) to Rational(-12, 1), + listOf(3u, 1u) to Rational(9, 1), + listOf(4u, 1u) to Rational(10, 3), + listOf(0u, 2u) to Rational(-27, 1), + listOf(1u, 2u) to Rational(-120, 1), + listOf(2u, 2u) to Rational(-84, 1), + listOf(3u, 2u) to Rational(12, 7), + listOf(4u, 2u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 12c" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(24, 7), + listOf(2u, 2u) to Rational(-6, 1), + listOf(0u, 3u) to Rational(-4, 1), + listOf(1u, 3u) to Rational(9, 1), + listOf(2u, 3u) to Rational(20, 3), + listOf(0u, 4u) to Rational(-14, 1), + listOf(1u, 4u) to Rational(6, 7), + listOf(2u, 4u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 13a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(-1, 2), + listOf(2u, 1u) to Rational(24, 7), + listOf(3u, 1u) to Rational(-4, 1), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(-12, 1), + listOf(2u, 2u) to Rational(27, 2), + listOf(3u, 2u) to Rational(20, 3), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(-56, 1), + listOf(2u, 3u) to Rational(12, 7), + listOf(3u, 3u) to Rational(80, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 13b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(8, 7), + listOf(4u) to Rational(-1, 1), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(-12, 1), + listOf(3u, 1u) to Rational(9, 1), + listOf(4u, 1u) to Rational(10, 3), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-84, 1), + listOf(3u, 2u) to Rational(12, 7), + listOf(4u, 2u) to Rational(60, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 13c" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1, 1), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(0u, 1u) to Rational(-22, 1), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-1, 4), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 14a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(2, 3), + listOf(1u) to Rational(-22, 1), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(0u, 1u) to Rational(-16, 5), + listOf(1u, 1u) to Rational(-1, 2), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 14b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(-20, 3), + listOf(1u) to Rational(-16, 5), + listOf(2u) to Rational(-1, 4), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthDerivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 14c" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_antiderivativeWithRespectTo_variable() { + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(1), + listOf(2u) to Rational(-1), + listOf(3u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).antiderivativeWithRespectTo(RationalField, 0), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(-6, 8), + listOf(2u) to Rational(-1, 3), + listOf(3u) to Rational(1, 6), + listOf(4u) to Rational(-11, 32), + listOf(5u) to Rational(18, 5), + listOf(1u, 1u) to Rational(-18, 3), + listOf(2u, 1u) to Rational(1, 3), + listOf(3u, 1u) to Rational(-11, 3), + listOf(4u, 1u) to Rational(-1, 12), + listOf(5u, 1u) to Rational(-18, 10), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(-4, 5), + listOf(3u, 2u) to Rational(-1, 24), + listOf(4u, 2u) to Rational(1, 7), + listOf(5u, 2u) to Rational(-1, 10), + listOf(1u, 3u) to Rational(3, 7), + listOf(2u, 3u) to Rational(1, 1), + listOf(3u, 3u) to Rational(-2, 3), + listOf(4u, 3u) to Rational(3, 8), + listOf(5u, 3u) to Rational(1, 9), + listOf(1u, 4u) to Rational(-18, 8), + listOf(2u, 4u) to Rational(-5, 1), + listOf(3u, 4u) to Rational(-7, 3), + listOf(4u, 4u) to Rational(1, 28), + listOf(5u, 4u) to Rational(1, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, 0), + "test 2a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(-6, 8), + listOf(1u, 1u) to Rational(-2, 3), + listOf(2u, 1u) to Rational(1, 2), + listOf(3u, 1u) to Rational(-11, 8), + listOf(4u, 1u) to Rational(18, 1), + listOf(0u, 2u) to Rational(-9, 3), + listOf(1u, 2u) to Rational(1, 3), + listOf(2u, 2u) to Rational(-11, 2), + listOf(3u, 2u) to Rational(-1, 6), + listOf(4u, 2u) to Rational(-9, 2), + listOf(0u, 3u) to Rational(-10, 9), + listOf(1u, 3u) to Rational(-8, 15), + listOf(2u, 3u) to Rational(-1, 24), + listOf(3u, 3u) to Rational(4, 21), + listOf(4u, 3u) to Rational(-1, 6), + listOf(0u, 4u) to Rational(3, 28), + listOf(1u, 4u) to Rational(1, 2), + listOf(2u, 4u) to Rational(-1, 2), + listOf(3u, 4u) to Rational(3, 8), + listOf(4u, 4u) to Rational(5, 36), + listOf(0u, 5u) to Rational(-9, 20), + listOf(1u, 5u) to Rational(-2, 1), + listOf(2u, 5u) to Rational(-7, 5), + listOf(3u, 5u) to Rational(1, 35), + listOf(4u, 5u) to Rational(1, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, 1), + "test 2b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(5u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(-1, 24), + listOf(4u, 2u) to Rational(1, 7), + listOf(5u, 2u) to Rational(-1, 10), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(-2, 3), + listOf(4u, 3u) to Rational(3, 8), + listOf(5u, 3u) to Rational(1, 9), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(-7, 3), + listOf(4u, 4u) to Rational(1, 28), + listOf(5u, 4u) to Rational(1, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, 0), + "test 3a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-1, 24), + listOf(3u, 3u) to Rational(4, 21), + listOf(4u, 3u) to Rational(-1, 6), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-1, 2), + listOf(3u, 4u) to Rational(3, 8), + listOf(4u, 4u) to Rational(5, 36), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(-7, 5), + listOf(3u, 5u) to Rational(1, 35), + listOf(4u, 5u) to Rational(1, 1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, 1), + "test 3b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(-6, 8), + listOf(2u) to Rational(-1, 3), + listOf(3u) to Rational(1, 6), + listOf(4u) to Rational(0), + listOf(5u) to Rational(0), + listOf(1u, 1u) to Rational(-18, 3), + listOf(2u, 1u) to Rational(1, 3), + listOf(3u, 1u) to Rational(-11, 3), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(1u, 2u) to Rational(-10, 3), + listOf(2u, 2u) to Rational(-4, 5), + listOf(3u, 2u) to Rational(-1, 24), + listOf(4u, 2u) to Rational(0), + listOf(5u, 2u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(5u, 3u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(5u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).antiderivativeWithRespectTo(RationalField, 0), + "test 4a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(-6, 8), + listOf(1u, 1u) to Rational(-2, 3), + listOf(2u, 1u) to Rational(1, 2), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-9, 3), + listOf(1u, 2u) to Rational(1, 3), + listOf(2u, 2u) to Rational(-11, 2), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(-10, 9), + listOf(1u, 3u) to Rational(-8, 15), + listOf(2u, 3u) to Rational(-1, 24), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(0), + listOf(3u, 5u) to Rational(0), + listOf(4u, 5u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).antiderivativeWithRespectTo(RationalField, 1), + "test 4b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 0u, 0u, 0u, 0u, 1u) to Rational(-6, 8), + listOf(1u, 0u, 0u, 0u, 0u, 1u) to Rational(-2, 3), + listOf(2u, 0u, 0u, 0u, 0u, 1u) to Rational(1, 2), + listOf(3u, 0u, 0u, 0u, 0u, 1u) to Rational(-11, 8), + listOf(4u, 0u, 0u, 0u, 0u, 1u) to Rational(18, 1), + listOf(0u, 1u, 0u, 0u, 0u, 1u) to Rational(-18, 3), + listOf(1u, 1u, 0u, 0u, 0u, 1u) to Rational(2, 3), + listOf(2u, 1u, 0u, 0u, 0u, 1u) to Rational(-11, 1), + listOf(3u, 1u, 0u, 0u, 0u, 1u) to Rational(-1, 3), + listOf(4u, 1u, 0u, 0u, 0u, 1u) to Rational(-18, 2), + listOf(0u, 2u, 0u, 0u, 0u, 1u) to Rational(-10, 3), + listOf(1u, 2u, 0u, 0u, 0u, 1u) to Rational(-8, 5), + listOf(2u, 2u, 0u, 0u, 0u, 1u) to Rational(-1, 8), + listOf(3u, 2u, 0u, 0u, 0u, 1u) to Rational(4, 7), + listOf(4u, 2u, 0u, 0u, 0u, 1u) to Rational(-4, 8), + listOf(0u, 3u, 0u, 0u, 0u, 1u) to Rational(3, 7), + listOf(1u, 3u, 0u, 0u, 0u, 1u) to Rational(16, 8), + listOf(2u, 3u, 0u, 0u, 0u, 1u) to Rational(-16, 8), + listOf(3u, 3u, 0u, 0u, 0u, 1u) to Rational(12, 8), + listOf(4u, 3u, 0u, 0u, 0u, 1u) to Rational(5, 9), + listOf(0u, 4u, 0u, 0u, 0u, 1u) to Rational(-18, 8), + listOf(1u, 4u, 0u, 0u, 0u, 1u) to Rational(-10, 1), + listOf(2u, 4u, 0u, 0u, 0u, 1u) to Rational(-14, 2), + listOf(3u, 4u, 0u, 0u, 0u, 1u) to Rational(1, 7), + listOf(4u, 4u, 0u, 0u, 0u, 1u) to Rational(15, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).antiderivativeWithRespectTo(RationalField, 5), + "test 5" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthAntiderivativeWithRespectTo_variable_order() { + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(1), + listOf(2u) to Rational(-1), + listOf(3u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 1u), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 0u), + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-1, 3), + listOf(4u) to Rational(1, 12), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 2u), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(3u) to Rational(1, 6), + listOf(4u) to Rational(-1, 12), + listOf(5u) to Rational(1, 60), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 3u), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(-1, 60), + listOf(6u) to Rational(1, 360), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 4u), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 0u), + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(1), + listOf(1u, 1u) to Rational(-2), + listOf(2u, 1u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 1u), + "test 7" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(1, 2), + listOf(1u, 2u) to Rational(-1), + listOf(2u, 2u) to Rational(1, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 2u), + "test 8" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(-3, 8), + listOf(3u) to Rational(-1, 9), + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(-11, 160), + listOf(6u) to Rational(3, 5), + listOf(2u, 1u) to Rational(-9, 3), + listOf(3u, 1u) to Rational(1, 9), + listOf(4u, 1u) to Rational(-11, 12), + listOf(5u, 1u) to Rational(-1, 60), + listOf(6u, 1u) to Rational(-3, 10), + listOf(2u, 2u) to Rational(-5, 3), + listOf(3u, 2u) to Rational(-4, 15), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(1, 35), + listOf(6u, 2u) to Rational(-1, 60), + listOf(2u, 3u) to Rational(3, 14), + listOf(3u, 3u) to Rational(1, 3), + listOf(4u, 3u) to Rational(-1, 6), + listOf(5u, 3u) to Rational(3, 40), + listOf(6u, 3u) to Rational(1, 54), + listOf(2u, 4u) to Rational(-9, 8), + listOf(3u, 4u) to Rational(-5, 3), + listOf(4u, 4u) to Rational(-7, 12), + listOf(5u, 4u) to Rational(1, 140), + listOf(6u, 4u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 2u), + "test 9a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(-3, 8), + listOf(1u, 2u) to Rational(-1, 3), + listOf(2u, 2u) to Rational(1, 4), + listOf(3u, 2u) to Rational(-11, 16), + listOf(4u, 2u) to Rational(9, 1), + listOf(0u, 3u) to Rational(-1, 1), + listOf(1u, 3u) to Rational(1, 9), + listOf(2u, 3u) to Rational(-11, 6), + listOf(3u, 3u) to Rational(-1, 18), + listOf(4u, 3u) to Rational(-9, 6), + listOf(0u, 4u) to Rational(-5, 18), + listOf(1u, 4u) to Rational(-2, 15), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(1, 21), + listOf(4u, 4u) to Rational(-1, 24), + listOf(0u, 5u) to Rational(3, 140), + listOf(1u, 5u) to Rational(1, 10), + listOf(2u, 5u) to Rational(-1, 10), + listOf(3u, 5u) to Rational(3, 40), + listOf(4u, 5u) to Rational(1, 36), + listOf(0u, 6u) to Rational(-3, 40), + listOf(1u, 6u) to Rational(-1, 3), + listOf(2u, 6u) to Rational(-7, 30), + listOf(3u, 6u) to Rational(1, 210), + listOf(4u, 6u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 2u), + "test 9b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(5u) to Rational(0), + listOf(6u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(6u, 1u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(1, 35), + listOf(6u, 2u) to Rational(-1, 60), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(-1, 6), + listOf(5u, 3u) to Rational(3, 40), + listOf(6u, 3u) to Rational(1, 54), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(-7, 12), + listOf(5u, 4u) to Rational(1, 140), + listOf(6u, 4u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 2u), + "test 10a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(1, 21), + listOf(4u, 4u) to Rational(-1, 24), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(-1, 10), + listOf(3u, 5u) to Rational(3, 40), + listOf(4u, 5u) to Rational(1, 36), + listOf(0u, 6u) to Rational(0), + listOf(1u, 6u) to Rational(0), + listOf(2u, 6u) to Rational(-7, 30), + listOf(3u, 6u) to Rational(1, 210), + listOf(4u, 6u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 2u), + "test 10b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(-3, 8), + listOf(3u) to Rational(-1, 9), + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(0), + listOf(6u) to Rational(0), + listOf(2u, 1u) to Rational(-9, 3), + listOf(3u, 1u) to Rational(1, 9), + listOf(4u, 1u) to Rational(-11, 12), + listOf(5u, 1u) to Rational(0), + listOf(6u, 1u) to Rational(0), + listOf(2u, 2u) to Rational(-5, 3), + listOf(3u, 2u) to Rational(-4, 15), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(0), + listOf(6u, 2u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(5u, 3u) to Rational(0), + listOf(6u, 3u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(5u, 4u) to Rational(0), + listOf(6u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 2u), + "test 11a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(-3, 8), + listOf(1u, 2u) to Rational(-1, 3), + listOf(2u, 2u) to Rational(1, 4), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(-1, 1), + listOf(1u, 3u) to Rational(1, 9), + listOf(2u, 3u) to Rational(-11, 6), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(-5, 18), + listOf(1u, 4u) to Rational(-2, 15), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(0), + listOf(3u, 5u) to Rational(0), + listOf(4u, 5u) to Rational(0), + listOf(0u, 6u) to Rational(0), + listOf(1u, 6u) to Rational(0), + listOf(2u, 6u) to Rational(0), + listOf(3u, 6u) to Rational(0), + listOf(4u, 6u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 2u), + "test 11b" + ) + } + @Test + @OptIn(UnstableKMathAPI::class) + fun test_Polynomial_nthAntiderivativeWithRespectTo_variablesAndOrders() { + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(1), + listOf(2u) to Rational(-1), + listOf(3u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 1u)), + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 0u), + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-1, 3), + listOf(4u) to Rational(1, 12), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 2u), + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(3u) to Rational(1, 6), + listOf(4u) to Rational(-1, 12), + listOf(5u) to Rational(1, 60), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 3u), + "test 4" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(-1, 60), + listOf(6u) to Rational(1, 360), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 0, 4u), + "test 5" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 0u), + "test 6" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(1), + listOf(1u, 1u) to Rational(-2), + listOf(2u, 1u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 1u), + "test 7" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(1, 2), + listOf(1u, 2u) to Rational(-1), + listOf(2u, 2u) to Rational(1, 2), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, 1, 2u), + "test 8" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf()), + "test 9" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u) to Rational(1), + listOf(2u) to Rational(-1), + listOf(3u) to Rational(1, 3), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf( + 0 to 1u, + 1 to 0u + )), + "test 10" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 1u) to Rational(1), + listOf(1u, 1u) to Rational(-2), + listOf(2u, 1u) to Rational(1), + ), + NumberedPolynomialAsIs( + listOf() to Rational(1), + listOf(1u) to Rational(-2), + listOf(2u) to Rational(1), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf( + 0 to 0u, + 1 to 1u + )), + "test 11" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(-3, 8), + listOf(3u) to Rational(-1, 9), + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(-11, 160), + listOf(6u) to Rational(3, 5), + listOf(2u, 1u) to Rational(-9, 3), + listOf(3u, 1u) to Rational(1, 9), + listOf(4u, 1u) to Rational(-11, 12), + listOf(5u, 1u) to Rational(-1, 60), + listOf(6u, 1u) to Rational(-3, 10), + listOf(2u, 2u) to Rational(-5, 3), + listOf(3u, 2u) to Rational(-4, 15), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(1, 35), + listOf(6u, 2u) to Rational(-1, 60), + listOf(2u, 3u) to Rational(3, 14), + listOf(3u, 3u) to Rational(1, 3), + listOf(4u, 3u) to Rational(-1, 6), + listOf(5u, 3u) to Rational(3, 40), + listOf(6u, 3u) to Rational(1, 54), + listOf(2u, 4u) to Rational(-9, 8), + listOf(3u, 4u) to Rational(-5, 3), + listOf(4u, 4u) to Rational(-7, 12), + listOf(5u, 4u) to Rational(1, 140), + listOf(6u, 4u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 12a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u, 1u) to Rational(-6, 8), + listOf(2u, 1u) to Rational(-1, 3), + listOf(3u, 1u) to Rational(1, 6), + listOf(4u, 1u) to Rational(-11, 32), + listOf(5u, 1u) to Rational(18, 5), + listOf(1u, 2u) to Rational(-9, 3), + listOf(2u, 2u) to Rational(1, 6), + listOf(3u, 2u) to Rational(-11, 6), + listOf(4u, 2u) to Rational(-1, 24), + listOf(5u, 2u) to Rational(-9, 10), + listOf(1u, 3u) to Rational(-10, 9), + listOf(2u, 3u) to Rational(-4, 15), + listOf(3u, 3u) to Rational(-1, 72), + listOf(4u, 3u) to Rational(1, 21), + listOf(5u, 3u) to Rational(-1, 30), + listOf(1u, 4u) to Rational(3, 28), + listOf(2u, 4u) to Rational(1, 4), + listOf(3u, 4u) to Rational(-1, 6), + listOf(4u, 4u) to Rational(3, 32), + listOf(5u, 4u) to Rational(1, 36), + listOf(1u, 5u) to Rational(-9, 20), + listOf(2u, 5u) to Rational(-1, 1), + listOf(3u, 5u) to Rational(-7, 15), + listOf(4u, 5u) to Rational(1, 140), + listOf(5u, 5u) to Rational(1, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 12b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(-3, 8), + listOf(1u, 2u) to Rational(-1, 3), + listOf(2u, 2u) to Rational(1, 4), + listOf(3u, 2u) to Rational(-11, 16), + listOf(4u, 2u) to Rational(9, 1), + listOf(0u, 3u) to Rational(-1, 1), + listOf(1u, 3u) to Rational(1, 9), + listOf(2u, 3u) to Rational(-11, 6), + listOf(3u, 3u) to Rational(-1, 18), + listOf(4u, 3u) to Rational(-9, 6), + listOf(0u, 4u) to Rational(-5, 18), + listOf(1u, 4u) to Rational(-2, 15), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(1, 21), + listOf(4u, 4u) to Rational(-1, 24), + listOf(0u, 5u) to Rational(3, 140), + listOf(1u, 5u) to Rational(1, 10), + listOf(2u, 5u) to Rational(-1, 10), + listOf(3u, 5u) to Rational(3, 40), + listOf(4u, 5u) to Rational(1, 36), + listOf(0u, 6u) to Rational(-3, 40), + listOf(1u, 6u) to Rational(-1, 3), + listOf(2u, 6u) to Rational(-7, 30), + listOf(3u, 6u) to Rational(1, 210), + listOf(4u, 6u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(-11, 8), + listOf(4u) to Rational(18, 1), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(-1, 3), + listOf(4u, 1u) to Rational(-18, 2), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(3, 7), + listOf(1u, 3u) to Rational(16, 8), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(-18, 8), + listOf(1u, 4u) to Rational(-10, 1), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 12c" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(5u) to Rational(0), + listOf(6u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(6u, 1u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(1, 35), + listOf(6u, 2u) to Rational(-1, 60), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(-1, 6), + listOf(5u, 3u) to Rational(3, 40), + listOf(6u, 3u) to Rational(1, 54), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(-7, 12), + listOf(5u, 4u) to Rational(1, 140), + listOf(6u, 4u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 13a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(5u, 2u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(-1, 72), + listOf(4u, 3u) to Rational(1, 21), + listOf(5u, 3u) to Rational(-1, 30), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(-1, 6), + listOf(4u, 4u) to Rational(3, 32), + listOf(5u, 4u) to Rational(1, 36), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(0), + listOf(3u, 5u) to Rational(-7, 15), + listOf(4u, 5u) to Rational(1, 140), + listOf(5u, 5u) to Rational(1, 5), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 13b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(0), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(1, 21), + listOf(4u, 4u) to Rational(-1, 24), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(-1, 10), + listOf(3u, 5u) to Rational(3, 40), + listOf(4u, 5u) to Rational(1, 36), + listOf(0u, 6u) to Rational(0), + listOf(1u, 6u) to Rational(0), + listOf(2u, 6u) to Rational(-7, 30), + listOf(3u, 6u) to Rational(1, 210), + listOf(4u, 6u) to Rational(1, 6), + ), + NumberedPolynomialAsIs( + listOf() to Rational(0), + listOf(1u) to Rational(0), + listOf(2u) to Rational(0), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(0), + listOf(1u, 1u) to Rational(0), + listOf(2u, 1u) to Rational(0), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(0), + listOf(1u, 2u) to Rational(0), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(4, 7), + listOf(4u, 2u) to Rational(-4, 8), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(-16, 8), + listOf(3u, 3u) to Rational(12, 8), + listOf(4u, 3u) to Rational(5, 9), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(-14, 2), + listOf(3u, 4u) to Rational(1, 7), + listOf(4u, 4u) to Rational(15, 3), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 13c" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to Rational(-3, 8), + listOf(3u) to Rational(-1, 9), + listOf(4u) to Rational(1, 24), + listOf(5u) to Rational(0), + listOf(6u) to Rational(0), + listOf(2u, 1u) to Rational(-9, 3), + listOf(3u, 1u) to Rational(1, 9), + listOf(4u, 1u) to Rational(-11, 12), + listOf(5u, 1u) to Rational(0), + listOf(6u, 1u) to Rational(0), + listOf(2u, 2u) to Rational(-5, 3), + listOf(3u, 2u) to Rational(-4, 15), + listOf(4u, 2u) to Rational(-1, 96), + listOf(5u, 2u) to Rational(0), + listOf(6u, 2u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(5u, 3u) to Rational(0), + listOf(6u, 3u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(5u, 4u) to Rational(0), + listOf(6u, 4u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 2u)), + "test 14a" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(1u, 1u) to Rational(-6, 8), + listOf(2u, 1u) to Rational(-1, 3), + listOf(3u, 1u) to Rational(1, 6), + listOf(4u, 1u) to Rational(0), + listOf(5u, 1u) to Rational(0), + listOf(1u, 2u) to Rational(-9, 3), + listOf(2u, 2u) to Rational(1, 6), + listOf(3u, 2u) to Rational(-11, 6), + listOf(4u, 2u) to Rational(0), + listOf(5u, 2u) to Rational(0), + listOf(1u, 3u) to Rational(-10, 9), + listOf(2u, 3u) to Rational(-4, 15), + listOf(3u, 3u) to Rational(-1, 72), + listOf(4u, 3u) to Rational(0), + listOf(5u, 3u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(5u, 4u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(0), + listOf(3u, 5u) to Rational(0), + listOf(4u, 5u) to Rational(0), + listOf(5u, 5u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(0 to 1u, 1 to 1u)), + "test 14b" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(0u, 2u) to Rational(-3, 8), + listOf(1u, 2u) to Rational(-1, 3), + listOf(2u, 2u) to Rational(1, 4), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(-1, 1), + listOf(1u, 3u) to Rational(1, 9), + listOf(2u, 3u) to Rational(-11, 6), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(-5, 18), + listOf(1u, 4u) to Rational(-2, 15), + listOf(2u, 4u) to Rational(-1, 96), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + listOf(0u, 5u) to Rational(0), + listOf(1u, 5u) to Rational(0), + listOf(2u, 5u) to Rational(0), + listOf(3u, 5u) to Rational(0), + listOf(4u, 5u) to Rational(0), + listOf(0u, 6u) to Rational(0), + listOf(1u, 6u) to Rational(0), + listOf(2u, 6u) to Rational(0), + listOf(3u, 6u) to Rational(0), + listOf(4u, 6u) to Rational(0), + ), + NumberedPolynomialAsIs( + listOf() to Rational(-6, 8), + listOf(1u) to Rational(-2, 3), + listOf(2u) to Rational(1, 2), + listOf(3u) to Rational(0), + listOf(4u) to Rational(0), + listOf(0u, 1u) to Rational(-18, 3), + listOf(1u, 1u) to Rational(2, 3), + listOf(2u, 1u) to Rational(-11, 1), + listOf(3u, 1u) to Rational(0), + listOf(4u, 1u) to Rational(0), + listOf(0u, 2u) to Rational(-10, 3), + listOf(1u, 2u) to Rational(-8, 5), + listOf(2u, 2u) to Rational(-1, 8), + listOf(3u, 2u) to Rational(0), + listOf(4u, 2u) to Rational(0), + listOf(0u, 3u) to Rational(0), + listOf(1u, 3u) to Rational(0), + listOf(2u, 3u) to Rational(0), + listOf(3u, 3u) to Rational(0), + listOf(4u, 3u) to Rational(0), + listOf(0u, 4u) to Rational(0), + listOf(1u, 4u) to Rational(0), + listOf(2u, 4u) to Rational(0), + listOf(3u, 4u) to Rational(0), + listOf(4u, 4u) to Rational(0), + ).nthAntiderivativeWithRespectTo(RationalField, mapOf(1 to 2u)), + "test 14c" + ) + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt new file mode 100644 index 000000000..ab912a464 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer + + +fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt new file mode 100644 index 000000000..a037dcd18 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.operations.Ring + + +class IntModulo { + val residue: Int + val modulus: Int + + @PublishedApi + internal constructor(residue: Int, modulus: Int, toCheckInput: Boolean = true) { + if (toCheckInput) { + require(modulus != 0) { "modulus can not be zero" } + this.modulus = if (modulus < 0) -modulus else modulus + this.residue = residue.mod(this.modulus) + } else { + this.residue = residue + this.modulus = modulus + } + } + + constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + + operator fun unaryPlus(): IntModulo = this + operator fun unaryMinus(): IntModulo = + IntModulo( + if (residue == 0) 0 else modulus - residue, + modulus, + toCheckInput = false + ) + operator fun plus(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not add two residue different modulo" } + return IntModulo( + (residue + other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun plus(other: Int): IntModulo = + IntModulo( + (residue + other) % modulus, + modulus, + toCheckInput = false + ) + operator fun minus(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not subtract two residue different modulo" } + return IntModulo( + (residue - other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun minus(other: Int): IntModulo = + IntModulo( + (residue - other) % modulus, + modulus, + toCheckInput = false + ) + operator fun times(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not multiply two residue different modulo" } + return IntModulo( + (residue * other.residue) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun times(other: Int): IntModulo = + IntModulo( + (residue * other) % modulus, + modulus, + toCheckInput = false + ) + operator fun div(other: IntModulo): IntModulo { + require(modulus == other.modulus) { "can not divide two residue different modulo" } + val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other.residue, modulus) + require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" } + return IntModulo( + (residue * reciprocalCandidate) % modulus, + modulus, + toCheckInput = false + ) + } + operator fun div(other: Int): IntModulo { + val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other, modulus) + require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" } + return IntModulo( + (residue * reciprocalCandidate) % modulus, + modulus, + toCheckInput = false + ) + } + override fun equals(other: Any?): Boolean = + when (other) { + is IntModulo -> residue == other.residue && modulus == other.modulus + else -> false + } + + override fun hashCode(): Int = residue.hashCode() + + override fun toString(): String = "$residue mod $modulus" +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") +class IntModuloRing : Ring { + + val modulus: Int + + constructor(modulus: Int) { + require(modulus != 0) { "modulus can not be zero" } + this.modulus = if (modulus < 0) -modulus else modulus + } + + override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) + override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false) + + fun number(arg: Int): IntModulo = IntModulo(arg, modulus, toCheckInput = false) + + override inline fun add(left: IntModulo, right: IntModulo): IntModulo = left + right + override inline fun multiply(left: IntModulo, right: IntModulo): IntModulo = left * right + + override inline fun IntModulo.unaryMinus(): IntModulo = -this + override inline fun IntModulo.plus(arg: IntModulo): IntModulo = this + arg + override inline fun IntModulo.minus(arg: IntModulo): IntModulo = this - arg + override inline fun IntModulo.times(arg: IntModulo): IntModulo = this * arg + inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt new file mode 100644 index 000000000..615523873 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.functions.PolynomialSpaceOverRing + + +fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) +fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, modulus) }) + +fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) +fun PolynomialSpaceOverRing.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt new file mode 100644 index 000000000..61b50f128 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import kotlin.math.abs + + +internal data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) + +internal tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) + +internal fun bezoutIdentityWithGCD(a: Int, b: Int): BezoutIdentityWithGCD = + when { + a < 0 && b < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, -second, gcd) } + a < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, second, gcd) } + b < 0 -> with(bezoutIdentityWithGCDInternalLogic(a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(first, -second, gcd) } + else -> bezoutIdentityWithGCDInternalLogic(a, b, 1, 0, 0, 1) + } + +internal tailrec fun bezoutIdentityWithGCDInternalLogic(a: Int, b: Int, m1: Int, m2: Int, m3: Int, m4: Int): BezoutIdentityWithGCD = + if (b == 0) BezoutIdentityWithGCD(m1, m3, a) + else { + val quotient = a / b + val reminder = a % b + bezoutIdentityWithGCDInternalLogic(b, reminder, m2, m1 - quotient * m2, m4, m3 - quotient * m4) + } \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt new file mode 100644 index 000000000..0a3d00e96 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2022 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. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps + +@Suppress("NAME_SHADOWING") +class Rational { + companion object { + val ZERO: Rational = Rational(0L) + val ONE: Rational = Rational(1L) + } + + val numerator: Long + val denominator: Long + + internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { + if (toCheckInput) { + if (denominator == 0L) throw ArithmeticException("/ by zero") + + val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < 0L) -it else it } + + this.numerator = numerator / greatestCommonDivider + this.denominator = denominator / greatestCommonDivider + } else { + this.numerator = numerator + this.denominator = denominator + } + } + + constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) + constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) + constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) + constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) + constructor(numerator: Int) : this(numerator.toLong(), 1L, false) + constructor(numerator: Long) : this(numerator, 1L, false) + + operator fun unaryPlus(): Rational = this + operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + operator fun plus(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val dividedThisDenominator = denominator / denominatorsGcd + val dividedOtherDenominator = other.denominator / denominatorsGcd + val numeratorCandidate = numerator * dividedOtherDenominator + dividedThisDenominator * other.numerator + val secondGcd = gcd(numeratorCandidate, denominatorsGcd) + return Rational( + numeratorCandidate / secondGcd, + dividedThisDenominator * (other.denominator / secondGcd), + toCheckInput = false + ) + } + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator, + toCheckInput = false + ) + operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator, + toCheckInput = false + ) + operator fun minus(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val dividedThisDenominator = denominator / denominatorsGcd + val dividedOtherDenominator = other.denominator / denominatorsGcd + val numeratorCandidate = numerator * dividedOtherDenominator - dividedThisDenominator * other.numerator + val secondGcd = gcd(numeratorCandidate, denominatorsGcd) + return Rational( + numeratorCandidate / secondGcd, + dividedThisDenominator * (other.denominator / secondGcd), + toCheckInput = false + ) + } + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator, + toCheckInput = false + ) + operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator, + toCheckInput = false + ) + operator fun times(other: Rational): Rational { + val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator) + val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator) + return Rational( + (numerator / otherDenominatorAndThisNumeratorGcd) * (other.numerator / thisDenominatorAndOtherNumeratorGcd), + (denominator / thisDenominatorAndOtherNumeratorGcd) * (other.denominator / otherDenominatorAndThisNumeratorGcd), + toCheckInput = false + ) + } + operator fun times(other: Int): Rational { + val other = other.toLong() + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + operator fun times(other: Long): Rational { + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + operator fun div(other: Rational): Rational { + val denominatorsGcd = gcd(denominator, other.denominator) + val numeratorsGcd = gcd(numerator, other.numerator) + return Rational( + (numerator / numeratorsGcd) * (other.denominator / denominatorsGcd), + (denominator / denominatorsGcd) * (other.numerator / numeratorsGcd) + ) + } + operator fun div(other: Int): Rational { + val other = other.toLong() + val numeratorAndOtherGcd = gcd(numerator, other) + return Rational( + numerator / numeratorAndOtherGcd, + denominator * (other / numeratorAndOtherGcd), + toCheckInput = false + ) + } + operator fun div(other: Long): Rational { + val numeratorAndOtherGcd = gcd(numerator, other) + return Rational( + numerator / numeratorAndOtherGcd, + denominator * (other / numeratorAndOtherGcd), + toCheckInput = false + ) + } + override fun equals(other: Any?): Boolean = + when (other) { + is Rational -> numerator == other.numerator && denominator == other.denominator + is Int -> numerator == other && denominator == 1L + is Long -> numerator == other && denominator == 1L + else -> false + } + + override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode() + + override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator" +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") +@OptIn(UnstableKMathAPI::class) +object RationalField : Field, NumbersAddOps { + override inline val zero: Rational get() = Rational.ZERO + override inline val one: Rational get() = Rational.ONE + + override inline fun number(value: Number): Rational = Rational(value.toLong()) + + override inline fun add(left: Rational, right: Rational): Rational = left + right + override inline fun multiply(left: Rational, right: Rational): Rational = left * right + override inline fun divide(left: Rational, right: Rational): Rational = left / right + override inline fun scale(a: Rational, value: Double): Rational = a * number(value) + + override inline fun Rational.unaryMinus(): Rational = -this + override inline fun Rational.plus(arg: Rational): Rational = this + arg + override inline fun Rational.minus(arg: Rational): Rational = this - arg + override inline fun Rational.times(arg: Rational): Rational = this * arg + override inline fun Rational.div(arg: Rational): Rational = this / arg +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt new file mode 100644 index 000000000..c70c229ca --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import space.kscience.kmath.functions.LabeledPolynomial +import space.kscience.kmath.functions.LabeledRationalFunction +import space.kscience.kmath.functions.NumberedPolynomial +import space.kscience.kmath.functions.NumberedRationalFunction +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + + +fun assertContentEquals( + expected: Map, + actual: Map, + absoluteTolerance: Double, + message: String? = null +) { + assertEquals(expected.keys, actual.keys, message) + for ((key, expectedValue) in expected) assertEquals(expectedValue, actual[key]!!, absoluteTolerance, message) +} + +fun assertEquals( + expected: NumberedPolynomial, + actual: NumberedPolynomial, + absoluteTolerance: Double, + message: String? = null +) { + assertContentEquals( + expected.coefficients, + actual.coefficients, + absoluteTolerance, + message + ) +} + +fun assertEquals( + expected: LabeledPolynomial, + actual: LabeledPolynomial, + absoluteTolerance: Double, + message: String? = null +) { + assertContentEquals( + expected.coefficients, + actual.coefficients, + absoluteTolerance, + message + ) +} + +fun assertEquals( + expected: NumberedRationalFunction, + actual: NumberedRationalFunction, + absoluteTolerance: Double, + message: String? = null +) { + assertEquals( + expected.numerator, + actual.numerator, + absoluteTolerance, + message + ) + assertEquals( + expected.denominator, + actual.denominator, + absoluteTolerance, + message + ) +} + +fun assertEquals( + expected: LabeledRationalFunction, + actual: LabeledRationalFunction, + absoluteTolerance: Double, + message: String? = null +) { + assertEquals( + expected.numerator, + actual.numerator, + absoluteTolerance, + message + ) + assertEquals( + expected.denominator, + actual.denominator, + absoluteTolerance, + message + ) +} + +inline fun assertFailsWithTypeAndMessage( + expectedMessage: String? = null, + assertionMessage: String? = null, + block: () -> Unit +) { + assertEquals( + expectedMessage, + assertFailsWith(T::class, assertionMessage, block).message, + assertionMessage + ) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt new file mode 100644 index 000000000..66e46c902 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2022 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.functions.testUtils + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol + + +val o: Rational = Rational(0) + +val x: Symbol by symbol +val y: Symbol by symbol +val z: Symbol by symbol +val t: Symbol by symbol +val s: Symbol by symbol +val iota: Symbol by symbol \ No newline at end of file diff --git a/kmath-stat/README.md b/kmath-stat/README.md index 80c6e0fcd..7ed20fcf4 100644 --- a/kmath-stat/README.md +++ b/kmath-stat/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-stat:0.3.0' + implementation 'space.kscience:kmath-stat:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-stat:0.3.0") + implementation("space.kscience:kmath-stat:0.3.1-dev-1") } ``` diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 41a1666f8..f6ca54e17 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,16 +1,16 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") } -kscience { - useAtomic() +kscience{ + native() } kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) + implementation(npmlibs.atomicfu) } } @@ -23,5 +23,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt index 8dbcb3367..cf2fd5b08 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt index 1218f13c5..14f49a35f 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt index cfc6eba04..8a249c340 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt index 25668446c..bb2bfdd09 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt index 63db1c56f..1ef2ec02c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt index 3997a77b3..a80407773 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -48,7 +48,8 @@ internal object InternalUtils { cache.copyInto( logFactorials, BEGIN_LOG_FACTORIALS, - BEGIN_LOG_FACTORIALS, endCopy + BEGIN_LOG_FACTORIALS, + endCopy, ) } else // All values to be computed diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt index 77d29981f..d861fddae 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index 993215d41..912bb0fa3 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt index 5390a2e09..34d1131b4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt index b3c014553..60a8491f2 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt index 9219df43e..4a4bfdfeb 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt index 0105731c4..145946b14 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt index 0a68e5c88..a8d289d47 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt index 83f87e832..3f6797881 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt index f0f94900e..83480b4ba 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt index b534fdc14..2cd561468 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt index 0e06fa162..37e6ea13b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt index aff7d03d9..fb14a95be 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt index c587277f9..87046cd46 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index d4bc36b5b..ac7977659 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt index f280a78aa..94b2bfbea 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index c96ecdc8c..66ade8119 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -8,6 +8,7 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.first import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.combine +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer @@ -30,10 +31,11 @@ public fun interface Sampler { /** * Sample a bunch of values */ +@OptIn(UnstableKMathAPI::class) public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory.boxing(), ): Chain> { require(size > 1) //creating temporary storage once diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index 1f442c09b..1e34fa434 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 43cd5b402..d7638ff81 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt index 20cc0e802..fa51bb521 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt index 5949213e7..38cd5f900 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt index 202a1c8dd..2da9a9e21 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 19c01e099..802f3ac24 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt index 075d7f3e5..889274c86 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -66,7 +66,7 @@ class MCScopeTest { } - @OptIn(ObsoleteCoroutinesApi::class) + @OptIn(DelicateCoroutinesApi::class) fun compareResult(test: ATest) { val res1 = runBlocking(Dispatchers.Default) { test() } val res2 = runBlocking(newSingleThreadContext("test")) { test() } diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt index 1dbbf591b..7b76fb4b6 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 9eb84899c..0db22fef4 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-symja/README.md b/kmath-symja/README.md index ea2d5d68f..a96b0e835 100644 --- a/kmath-symja/README.md +++ b/kmath-symja/README.md @@ -6,7 +6,7 @@ Symja integration module ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-symja:0.3.0' + implementation 'space.kscience:kmath-symja:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-symja:0.3.0") + implementation("space.kscience:kmath-symja:0.3.1-dev-1") } ``` diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts index 65c329d52..8741de2ae 100644 --- a/kmath-symja/build.gradle.kts +++ b/kmath-symja/build.gradle.kts @@ -4,8 +4,7 @@ */ plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } description = "Symja integration module" @@ -38,5 +37,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt index 3067b5efb..0f8014913 100644 --- a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt index 30c37c799..92f2474b8 100644 --- a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensorflow/README.md b/kmath-tensorflow/README.md index 7852c07be..83f2eb315 100644 --- a/kmath-tensorflow/README.md +++ b/kmath-tensorflow/README.md @@ -6,7 +6,7 @@ Google tensorflow connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensorflow:0.3.0' + implementation 'space.kscience:kmath-tensorflow:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensorflow:0.3.0") + implementation("space.kscience:kmath-tensorflow:0.3.1-dev-1") } ``` diff --git a/kmath-tensorflow/build.gradle.kts b/kmath-tensorflow/build.gradle.kts index 9380a7308..1e4ba12da 100644 --- a/kmath-tensorflow/build.gradle.kts +++ b/kmath-tensorflow/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") } description = "Google tensorflow connector" @@ -11,5 +11,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt index ecfd8d098..c4d192792 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 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.tensorflow import org.tensorflow.Graph @@ -7,6 +12,7 @@ import org.tensorflow.op.core.Constant import org.tensorflow.types.TFloat64 import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND @@ -74,6 +80,7 @@ public class DoubleTensorFlowAlgebra internal constructor( * * The resulting tensor is available outside of scope */ +@UnstableKMathAPI public fun DoubleField.produceWithTF( block: DoubleTensorFlowAlgebra.() -> StructureND, ): StructureND = Graph().use { graph -> @@ -86,6 +93,7 @@ public fun DoubleField.produceWithTF( * * The resulting tensors are available outside of scope */ +@OptIn(UnstableKMathAPI::class) public fun DoubleField.produceMapWithTF( block: DoubleTensorFlowAlgebra.() -> Map>, ): Map> = Graph().use { graph -> diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt index 084a445e0..01c8054b3 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 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.tensorflow import org.tensorflow.Graph diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt index 7185b84d6..74fcf2d7d 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 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.tensorflow @@ -179,11 +184,11 @@ public abstract class TensorFlowAlgebra> internal c override fun StructureND.unaryMinus(): TensorFlowOutput = operate(ops.math::neg) - override fun Tensor.get(i: Int): Tensor = operate { + override fun Tensor.getTensor(i: Int): Tensor = operate { StridedSliceHelper.stridedSlice(ops.scope(), it, Indices.at(i.toLong())) } - override fun Tensor.transpose(i: Int, j: Int): Tensor = operate { + override fun Tensor.transposed(i: Int, j: Int): Tensor = operate { ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } @@ -233,6 +238,11 @@ public abstract class TensorFlowAlgebra> internal c ops.min(it, ops.constant(dim), Min.keepDims(keepDim)) } + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = IntTensorFlowOutput( + graph, + ops.math.argMin(asTensorFlow().output, ops.constant(dim), TInt32::class.java).output() + ).actualTensor + override fun StructureND.max(): T = operate { ops.max(it, ops.constant(intArrayOf())) }.value() diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt index f67c333ce..a0a2ddc80 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt index 308469eed..a35556be1 100644 --- a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt +++ b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt @@ -1,6 +1,12 @@ +/* + * Copyright 2018-2022 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.tensorflow import org.junit.jupiter.api.Test +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField @@ -8,6 +14,7 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.sum import kotlin.test.assertEquals +@OptIn(UnstableKMathAPI::class) class DoubleTensorFlowOps { @Test fun basicOps() { diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 44ee47675..4208cd83d 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0' + implementation 'space.kscience:kmath-tensors:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0") + implementation("space.kscience:kmath-tensors:0.3.1-dev-1") } ``` diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 66316d21d..1060b37b4 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -1,7 +1,13 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() + dependencies { + api(projects.kmathCore) + api(projects.kmathStat) + } } kotlin.sourceSets { @@ -19,10 +25,16 @@ kotlin.sourceSets { api(project(":kmath-stat")) } } + + commonTest{ + dependencies{ + implementation(projects.testUtils) + } + } } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 3ed34ae5e..587096500 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 0bddc3f9c..07dfd1597 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt index 482bb5244..b328fbeec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 86d4eaa4e..70b985a54 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -166,7 +166,11 @@ public interface TensorAlgebra> : RingOpsND { * @param i index of the extractable tensor * @return subtensor of the original tensor with index [i] */ - public operator fun Tensor.get(i: Int): Tensor + public fun Tensor.getTensor(i: Int): Tensor + + public fun Tensor.getTensor(first: Int, second: Int): Tensor { + return getTensor(first).getTensor(second) + } /** * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. @@ -176,7 +180,7 @@ public interface TensorAlgebra> : RingOpsND { * @param j the second dimension to be transposed * @return transposed tensor */ - public fun Tensor.transpose(i: Int = -2, j: Int = -1): Tensor + public fun Tensor.transposed(i: Int = -2, j: Int = -1): Tensor /** * Returns a new tensor with the same data as the self tensor but of a different shape. @@ -213,16 +217,7 @@ public interface TensorAlgebra> : RingOpsND { * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, * the matrix-vector product is returned. * - * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), - * then a batched matrix multiply is returned. If the first argument is 1-dimensional, - * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. - * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix - * multiple and removed after. - * The non-matrix (i.e., batch) dimensions are broadcast (and thus must be broadcastable). - * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a - * (k × n × n) tensor, out will be a (j × k × n × n) tensor. - * - * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * Otherwise, throw an exception. * * @param other tensor to be multiplied. * @return a mathematical product of two tensors. @@ -295,6 +290,19 @@ public interface TensorAlgebra> : RingOpsND { */ public fun StructureND.min(dim: Int, keepDim: Boolean): Tensor + /** + * Returns the index of minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the index of maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor + /** * Returns the maximum value of all elements in the input tensor or null if there are no values */ @@ -329,4 +337,4 @@ public interface TensorAlgebra> : RingOpsND { override fun add(left: StructureND, right: StructureND): Tensor = left + right override fun multiply(left: StructureND, right: StructureND): Tensor = left * right -} +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 9c492cda1..33effb2d2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e412ab5bb..f337a2175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -1,98 +1,88 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.broadcastTensors import space.kscience.kmath.tensors.core.internal.broadcastTo -import space.kscience.kmath.tensors.core.internal.tensor /** * Basic linear algebra operations implemented with broadcasting. * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html */ - -@PerformancePitfall public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun StructureND.plus(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] + newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.plusAssign(arg: StructureND) { - val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until asDoubleTensor().indices.linearSize) { + asDoubleTensor().source[i] += newOther.source[i] } } override fun StructureND.minus(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] - newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.minusAssign(arg: StructureND) { - val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[i] -= newOther.source[i] } } override fun StructureND.times(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newThis.bufferStart + i] * - newOther.mutableBuffer.array()[newOther.bufferStart + i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] * newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.timesAssign(arg: StructureND) { - val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[+i] *= newOther.source[i] } } override fun StructureND.div(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newOther.bufferStart + i] / - newOther.mutableBuffer.array()[newOther.bufferStart + i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] / newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.divAssign(arg: StructureND) { - val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[i] /= newOther.source[i] } } } @@ -102,6 +92,5 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { * Compute a value using broadcast double tensor algebra */ @UnstableKMathAPI -@PerformancePitfall public fun DoubleTensorAlgebra.withBroadcast(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra.block() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 73a89502c..0b043db56 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -13,12 +13,12 @@ import space.kscience.kmath.tensors.api.Tensor /** * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ -public open class BufferedTensor internal constructor( +public abstract class BufferedTensor( override val shape: IntArray, - @PublishedApi internal val mutableBuffer: MutableBuffer, - @PublishedApi internal val bufferStart: Int, ) : Tensor { + public abstract val source: MutableBuffer + /** * Buffer strides based on [TensorLinearStructure] implementation */ @@ -27,14 +27,8 @@ public open class BufferedTensor internal constructor( /** * Number of elements in tensor */ - public val numElements: Int - get() = indices.linearSize + public val linearSize: Int get() = indices.linearSize - override fun get(index: IntArray): T = mutableBuffer[bufferStart + indices.offset(index)] - - override fun set(index: IntArray, value: T) { - mutableBuffer[bufferStart + indices.offset(index)] = value - } @PerformancePitfall override fun elements(): Sequence> = indices.asSequence().map { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt index 8e5116336..e9589eb0a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -1,20 +1,92 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core -import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString +public class OffsetDoubleBuffer( + private val source: DoubleBuffer, + private val offset: Int, + override val size: Int, +) : MutableBuffer { + + init { + require(offset >= 0) { "Offset must be non-negative" } + require(size >= 0) { "Size must be non-negative" } + require(offset + size <= source.size) { "Maximum index must be inside source dimension" } + } + + override fun set(index: Int, value: Double) { + require(index in 0 until size) { "Index must be in [0, size)" } + source[index + offset] = value + } + + override fun get(index: Int): Double = source[index + offset] + + /** + * Copy only a part of buffer that belongs to this tensor + */ + override fun copy(): DoubleBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() + + override fun iterator(): Iterator = iterator { + for (i in indices) { + yield(get(i)) + } + } + + override fun toString(): String = Buffer.toString(this) + + public fun view(addOffset: Int, newSize: Int = size - addOffset): OffsetDoubleBuffer = + OffsetDoubleBuffer(source, offset + addOffset, newSize) +} + +public fun OffsetDoubleBuffer.slice(range: IntRange): OffsetDoubleBuffer = view(range.first, range.last - range.first) + +/** + * Map only operable content of the offset buffer + */ +public inline fun OffsetDoubleBuffer.map(operation: (Double) -> Double): DoubleBuffer = + DoubleBuffer(size) { operation(get(it)) } + +public inline fun OffsetDoubleBuffer.zip( + other: OffsetDoubleBuffer, + operation: (l: Double, r: Double) -> Double, +): DoubleBuffer { + require(size == other.size) { "The sizes of zipped buffers must be the same" } + return DoubleBuffer(size) { operation(get(it), other[it]) } +} + +/** + * map in place + */ +public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { + indices.forEach { set(it, operation(get(it))) } +} + /** * Default [BufferedTensor] implementation for [Double] values */ -public class DoubleTensor @PublishedApi internal constructor( +public class DoubleTensor( shape: IntArray, - buffer: DoubleArray, - offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + override val source: OffsetDoubleBuffer, +) : BufferedTensor(shape) { + + init { + require(linearSize == source.size) { "Source buffer size must be equal tensor size" } + } + + public constructor(shape: IntArray, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) + + override fun get(index: IntArray): Double = this.source[indices.offset(index)] + + override fun set(index: IntArray, value: Double) { + source[indices.offset(index)] = value + } + + override fun toString(): String = toPrettyString() } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index e9dc34748..f563d00ae 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -9,10 +9,10 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.indices +import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.Tensor @@ -23,6 +23,7 @@ import kotlin.math.* /** * Implementation of basic operations over double tensors and basic algebra operations on them. */ +@OptIn(PerformancePitfall::class) public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, AnalyticTensorAlgebra, @@ -30,8 +31,7 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override val elementAlgebra: DoubleField - get() = DoubleField + override val elementAlgebra: DoubleField get() = DoubleField /** @@ -40,56 +40,64 @@ public open class DoubleTensorAlgebra : * @param transform the function to be applied to each element of the tensor. * @return the resulting tensor after applying the function. */ - @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.map(transform: DoubleField.(Double) -> Double): DoubleTensor { - val tensor = this.tensor + val tensor = asDoubleTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = DoubleArray(tensor.numElements) { DoubleField.transform(sourceArray[it]) } + val array = DoubleBuffer(tensor.source.size) { DoubleField.transform(tensor.source[it]) } return DoubleTensor( tensor.shape, array, - tensor.bufferStart ) } - @PerformancePitfall + public inline fun Tensor.mapInPlace(operation: (Double) -> Double) { + if (this is DoubleTensor) { + source.mapInPlace(operation) + } else { + indices.forEach { set(it, operation(get(it))) } + } + } + + public inline fun Tensor.mapIndexedInPlace(operation: (IntArray, Double) -> Double) { + indices.forEach { set(it, operation(it, get(it))) } + } + @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: DoubleField.(index: IntArray, Double) -> Double): DoubleTensor { - val tensor = this.tensor + val tensor = this.asDoubleTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = DoubleArray(tensor.numElements) { DoubleField.transform(tensor.indices.index(it), sourceArray[it]) } - return DoubleTensor( - tensor.shape, - array, - tensor.bufferStart - ) + val buffer = DoubleBuffer(tensor.source.size) { + DoubleField.transform(tensor.indices.index(it), tensor.source[it]) + } + return DoubleTensor(tensor.shape, buffer) } - @PerformancePitfall - override fun zip( + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun zip( left: StructureND, right: StructureND, transform: DoubleField.(Double, Double) -> Double, ): DoubleTensor { - require(left.shape.contentEquals(right.shape)) { - "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" + checkShapesCompatible(left, right) + + val leftTensor = left.asDoubleTensor() + val rightTensor = right.asDoubleTensor() + val buffer = DoubleBuffer(leftTensor.source.size) { + DoubleField.transform(leftTensor.source[it], rightTensor.source[it]) } - val leftTensor = left.tensor - val leftArray = leftTensor.copyArray() - val rightTensor = right.tensor - val rightArray = rightTensor.copyArray() - val array = DoubleArray(leftTensor.numElements) { DoubleField.transform(leftArray[it], rightArray[it]) } - return DoubleTensor( - leftTensor.shape, - array - ) + return DoubleTensor(leftTensor.shape, buffer) } - override fun StructureND.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) - tensor.mutableBuffer.array()[tensor.bufferStart] else null + + public inline fun StructureND.reduceElements(transform: (DoubleBuffer) -> Double): Double = + transform(asDoubleTensor().source.copy()) + //TODO do we need protective copy? + + override fun StructureND.valueOrNull(): Double? { + val dt = asDoubleTensor() + return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + } override fun StructureND.value(): Double = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -98,14 +106,14 @@ public open class DoubleTensorAlgebra : * Constructs a tensor with the specified shape and data. * * @param shape the desired shape for the tensor. - * @param buffer one-dimensional data array. - * @return tensor with the [shape] shape and [buffer] data. + * @param array one-dimensional data array. + * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { - checkEmptyShape(shape) - checkEmptyDoubleBuffer(buffer) - checkBufferShapeConsistency(shape, buffer) - return DoubleTensor(shape, buffer, 0) + public fun fromArray(shape: IntArray, array: DoubleArray): DoubleTensor { + checkNotEmptyShape(shape) + checkEmptyDoubleBuffer(array) + checkBufferShapeConsistency(shape, array) + return DoubleTensor(shape, array.asBuffer()) } /** @@ -120,11 +128,14 @@ public open class DoubleTensorAlgebra : TensorLinearStructure(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) - override operator fun Tensor.get(i: Int): DoubleTensor { - val lastShape = tensor.shape.drop(1).toIntArray() + override fun Tensor.getTensor(i: Int): DoubleTensor { + val dt = asDoubleTensor() + val lastShape = shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart - return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) + return DoubleTensor( + newShape, + dt.source.view(newShape.reduce(Int::times) * i, TensorLinearStructure.linearSizeOf(newShape)) + ) } /** @@ -135,8 +146,8 @@ public open class DoubleTensorAlgebra : * @return tensor with the [shape] shape and filled with [value]. */ public fun full(value: Double, shape: IntArray): DoubleTensor { - checkEmptyShape(shape) - val buffer = DoubleArray(shape.reduce(Int::times)) { value } + checkNotEmptyShape(shape) + val buffer = DoubleBuffer(shape.reduce(Int::times)) { value } return DoubleTensor(shape, buffer) } @@ -146,9 +157,9 @@ public open class DoubleTensorAlgebra : * @param value the value to fill the output tensor with. * @return tensor with the `input` tensor shape and filled with [value]. */ - public fun Tensor.fullLike(value: Double): DoubleTensor { - val shape = tensor.shape - val buffer = DoubleArray(tensor.numElements) { value } + public fun fullLike(structureND: StructureND<*>, value: Double): DoubleTensor { + val shape = structureND.shape + val buffer = DoubleBuffer(structureND.indices.linearSize) { value } return DoubleTensor(shape, buffer) } @@ -165,7 +176,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `0.0`, with the same shape as `input` tensor. */ - public fun StructureND.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + public fun zeroesLike(structureND: StructureND<*>): DoubleTensor = fullLike(structureND, 0.0) /** * Returns a tensor filled with the scalar value `1.0`, with the shape defined by the variable argument [shape]. @@ -180,7 +191,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `1.0`, with the same shape as `input` tensor. */ - public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) + public fun onesLike(structureND: StructureND<*>): DoubleTensor = fullLike(structureND, 1.0) /** * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. @@ -190,7 +201,7 @@ public open class DoubleTensorAlgebra : */ public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) - val buffer = DoubleArray(n * n) { 0.0 } + val buffer = DoubleBuffer(n * n) { 0.0 } val res = DoubleTensor(shape, buffer) for (i in 0 until n) { res[intArrayOf(i, i)] = 1.0 @@ -198,209 +209,156 @@ public open class DoubleTensorAlgebra : return res } - /** - * Return a copy of the tensor. - * - * @return a copy of the `input` tensor with a copied buffer. - */ - public fun StructureND.copy(): DoubleTensor = - DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) + override fun Double.plus(arg: StructureND): DoubleTensor = arg.map { this@plus + it } - override fun Double.plus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun StructureND.plus(arg: Double): DoubleTensor = map { it + arg } - override fun StructureND.plus(arg: Double): DoubleTensor = arg + tensor - - override fun StructureND.plus(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg.tensor) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i] - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.plus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l + r } override fun Tensor.plusAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += value - } + mapInPlace { it + value } } override fun Tensor.plusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg.tensor) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg.asDoubleTensor()) + mapIndexedInPlace { index, value -> + value + arg[index] } } - override fun Double.minus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.minus(arg: StructureND): DoubleTensor = arg.map { this@minus - it } - override fun StructureND.minus(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] - arg - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.minus(arg: Double): DoubleTensor = map { it - arg } - override fun StructureND.minus(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i] - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.minus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l - r } override fun Tensor.minusAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value - } + mapInPlace { it - value } } override fun Tensor.minusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value - arg[index] } } - override fun Double.times(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] * this - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.times(arg: StructureND): DoubleTensor = arg.map { this@times * it } - override fun StructureND.times(arg: Double): DoubleTensor = arg * tensor + override fun StructureND.times(arg: Double): DoubleTensor = arg * asDoubleTensor() - override fun StructureND.times(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] * - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.times(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l * r } override fun Tensor.timesAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value - } + mapInPlace { it * value } } override fun Tensor.timesAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value * arg[index] } } - override fun Double.div(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this / arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.div(arg: StructureND): DoubleTensor = arg.map { this@div / it } - override fun StructureND.div(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] / arg - } - return DoubleTensor(shape, resBuffer) - } + override fun StructureND.div(arg: Double): DoubleTensor = map { it / arg } - override fun StructureND.div(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] / - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.div(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l / r } override fun Tensor.divAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value - } + mapInPlace { it / value } } override fun Tensor.divAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] - } + checkShapesCompatible(asDoubleTensor(), arg) + mapIndexedInPlace { index, value -> value / arg[index] } } - override fun StructureND.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() - } - return DoubleTensor(tensor.shape, resBuffer) - } + override fun StructureND.unaryMinus(): DoubleTensor = map { -it } - override fun Tensor.transpose(i: Int, j: Int): DoubleTensor { - val ii = tensor.minusIndex(i) - val jj = tensor.minusIndex(j) - checkTranspose(tensor.dimension, ii, jj) - val n = tensor.numElements + override fun Tensor.transposed(i: Int, j: Int): DoubleTensor { + // TODO change strides instead of changing content + val dt = asDoubleTensor() + val ii = dt.minusIndex(i) + val jj = dt.minusIndex(j) + checkTranspose(dt.dimension, ii, jj) + val n = dt.linearSize val resBuffer = DoubleArray(n) - val resShape = tensor.shape.copyOf() + val resShape = dt.shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } - val resTensor = DoubleTensor(resShape, resBuffer) + val resTensor = DoubleTensor(resShape, resBuffer.asBuffer()) for (offset in 0 until n) { - val oldMultiIndex = tensor.indices.index(offset) + val oldMultiIndex = dt.indices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + offset] + resTensor.source[linearIndex] = dt.source[offset] } return resTensor } override fun Tensor.view(shape: IntArray): DoubleTensor { - checkView(tensor, shape) - return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) + checkView(asDoubleTensor(), shape) + return DoubleTensor(shape, asDoubleTensor().source) } override fun Tensor.viewAs(other: StructureND): DoubleTensor = - tensor.view(other.shape) + view(other.shape) - override infix fun StructureND.dot(other: StructureND): DoubleTensor { - if (tensor.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) + /** + * Broadcasting Matrix product of two tensors. + * + * The behavior depends on the dimensionality of the tensors as follows: + * 1. If both tensors are 1-dimensional, the dot product (scalar) is returned. + * + * 2. If both arguments are 2-dimensional, the matrix-matrix product is returned. + * + * 3. If the first argument is 1-dimensional and the second argument is 2-dimensional, + * a 1 is prepended to its dimension for the purpose of the matrix multiply. + * After the matrix multiply, depending on the implementation the prepended dimension might be removed. + * + * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, + * the matrix-vector product is returned. + * + * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), + * then a batched matrix multiply is returned. If the first argument is 1-dimensional, + * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. + * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix + * multiple and removed after. + * The non-matrix (i.e., batch) dimensions are broadcast (and thus must be broadcastable). + * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a + * (k × n × n) tensor, out will be a (j × k × n × n) tensor. + * + * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * + * @param other tensor to be multiplied. + * @return a mathematical product of two tensors. + */ + @UnstableKMathAPI + public infix fun StructureND.matmul(other: StructureND): DoubleTensor { + if (shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), DoubleBuffer(times(other).sum())) } - var newThis = tensor.copy() - var newOther = other.copy() - var penultimateDim = false var lastDim = false - if (tensor.shape.size == 1) { + + //TODO do we need protective copy here? + var newThis: DoubleTensor = copyToTensor() + var newOther: DoubleTensor = other.copyToTensor() + + if (shape.size == 1) { penultimateDim = true - newThis = tensor.view(intArrayOf(1) + tensor.shape) - } - if (other.shape.size == 1) { - lastDim = true - newOther = other.tensor.view(other.shape + intArrayOf(1)) + newThis = newThis.view(intArrayOf(1) + shape) } - val broadcastTensors = broadcastOuterTensors(newThis.tensor, newOther.tensor) + if (other.shape.size == 1) { + lastDim = true + newOther = newOther.view(other.shape + intArrayOf(1)) + } + + val broadcastTensors = broadcastOuterTensors(newThis, newOther) newThis = broadcastTensors[0] newOther = broadcastTensors[1] @@ -414,12 +372,20 @@ public open class DoubleTensorAlgebra : val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) val resSize = resShape.reduce { acc, i -> acc * i } - val resTensor = DoubleTensor(resShape, DoubleArray(resSize)) + val resTensor = DoubleTensor(resShape, DoubleArray(resSize).asBuffer()) - for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { - val (a, b) = ab - dotTo(a, b, res, l, m1, n) + val resMatrices = resTensor.matrices + val newThisMatrices = newThis.matrices + val newOtherMatrices = newOther.matrices + + for (i in resMatrices.indices) { + dotTo(newThisMatrices[i], newOtherMatrices[i], resMatrices[i], l, m1, n) } +// +// for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { +// val (a, b) = ab +// dotTo(a, b, res, l, m1, n) +// } return if (penultimateDim) { resTensor.view(resTensor.shape.dropLast(2).toIntArray() + intArrayOf(resTensor.shape.last())) @@ -430,6 +396,11 @@ public open class DoubleTensorAlgebra : } } + override fun StructureND.dot(other: StructureND): DoubleTensor { + return if (dimension in 0..2 && other.dimension in 0..2) matmul(other) + else error("Only vectors and matrices are allowed in non-broadcasting dot operation") + } + override fun diagonalEmbedding( diagonalEntries: Tensor, offset: Int, @@ -460,10 +431,10 @@ public open class DoubleTensorAlgebra : diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() - val resTensor = zeros(resShape) + val resTensor: DoubleTensor = zeros(resShape) - for (i in 0 until diagonalEntries.tensor.numElements) { - val multiIndex = diagonalEntries.tensor.indices.index(i) + for (i in 0 until diagonalEntries.indices.linearSize) { + val multiIndex = diagonalEntries.indices.index(i) var offset1 = 0 var offset2 = abs(realOffset) @@ -479,7 +450,7 @@ public open class DoubleTensorAlgebra : resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] } - return resTensor.tensor + return resTensor } /** @@ -490,7 +461,7 @@ public open class DoubleTensorAlgebra : * @return true if two tensors have the same shape and elements, false otherwise. */ public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean = - tensor.eq(other) { x, y -> abs(x - y) < epsilon } + asDoubleTensor().eq(other) { x, y -> abs(x - y) < epsilon } /** * Compares element-wise two tensors. @@ -499,23 +470,20 @@ public open class DoubleTensorAlgebra : * @param other the tensor to compare with `input` tensor. * @return true if two tensors have the same shape and elements, false otherwise. */ - public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) + public infix fun Tensor.eq(other: Tensor): Boolean = eq(other, 1e-5) private fun Tensor.eq( other: Tensor, eqFunction: (Double, Double) -> Boolean, ): Boolean { - checkShapesCompatible(tensor, other) - val n = tensor.numElements - if (n != other.tensor.numElements) { + //TODO optimize tensor conversion + checkShapesCompatible(asDoubleTensor(), other) + val n = asDoubleTensor().linearSize + if (n != other.asDoubleTensor().linearSize) { return false } for (i in 0 until n) { - if (!eqFunction( - tensor.mutableBuffer[tensor.bufferStart + i], - other.tensor.mutableBuffer[other.tensor.bufferStart + i] - ) - ) { + if (!eqFunction(asDoubleTensor().source[i], other.asDoubleTensor().source[i])) { return false } } @@ -543,7 +511,7 @@ public open class DoubleTensorAlgebra : * with `0.0` mean and `1.0` standard deviation. */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = - DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) + DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) /** * Concatenates a sequence of tensors with equal shapes along the first dimension. @@ -556,10 +524,12 @@ public open class DoubleTensorAlgebra : val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape - val resBuffer = tensors.flatMap { - it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) - }.toDoubleArray() - return DoubleTensor(resShape, resBuffer, 0) +// val resBuffer: List = tensors.flatMap { +// it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart) +// .take(it.asDoubleTensor().linearSize) +// } + val resBuffer = tensors.map { it.asDoubleTensor().source }.concat() + return DoubleTensor(resShape, resBuffer) } /** @@ -568,16 +538,14 @@ public open class DoubleTensorAlgebra : * @param indices the [IntArray] of 1-dimensional indices * @return tensor with rows corresponding to row by [indices] */ - public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { this[it] }) + public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { getTensor(it) }) - private inline fun StructureND.fold(foldFunction: (DoubleArray) -> Double): Double = - foldFunction(tensor.copyArray()) - private inline fun StructureND.foldDim( + private inline fun StructureND.foldDimToDouble( dim: Int, keepDim: Boolean, - foldFunction: (DoubleArray) -> R, - ): BufferedTensor { + foldFunction: (DoubleArray) -> Double, + ): DoubleTensor { check(dim < dimension) { "Dimension $dim out of range $dimension" } val resShape = if (keepDim) { shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() @@ -586,76 +554,113 @@ public open class DoubleTensorAlgebra : } val resNumElements = resShape.reduce(Int::times) val init = foldFunction(DoubleArray(1) { 0.0 }) - val resTensor = BufferedTensor(resShape, - MutableBuffer.auto(resNumElements) { init }, 0) + val resTensor = DoubleTensor( + resShape, + DoubleBuffer(resNumElements) { init } + ) + val dt = asDoubleTensor() for (index in resTensor.indices) { val prefix = index.take(dim).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray() resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> - tensor[prefix + intArrayOf(i) + suffix] + dt[prefix + intArrayOf(i) + suffix] }) } return resTensor } - override fun StructureND.sum(): Double = tensor.fold { it.sum() } + private inline fun StructureND.foldDimToInt( + dim: Int, + keepDim: Boolean, + foldFunction: (DoubleArray) -> Int, + ): IntTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val init = foldFunction(DoubleArray(1) { 0.0 }) + val resTensor = IntTensor( + resShape, + IntBuffer(resNumElements) { init } + ) + for (index in resTensor.indices) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + asDoubleTensor()[prefix + intArrayOf(i) + suffix] + }) + } + return resTensor + } + + + override fun StructureND.sum(): Double = reduceElements { it.array.sum() } override fun StructureND.sum(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.sum() }.toDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.sum() } - override fun StructureND.min(): Double = this.fold { it.minOrNull()!! } + override fun StructureND.min(): Double = reduceElements { it.array.min() } override fun StructureND.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.minOrNull()!! }.toDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.minOrNull()!! } - override fun StructureND.max(): Double = this.fold { it.maxOrNull()!! } + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDimToInt(dim, keepDim) { x -> + x.withIndex().minBy { it.value }.index + } + + override fun StructureND.max(): Double = reduceElements { it.array.max() } override fun StructureND.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.toDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.maxOrNull()!! } override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> - x.withIndex().maxByOrNull { it.value }?.index!! - }.toIntTensor() + foldDimToInt(dim, keepDim) { x -> + x.withIndex().maxBy { it.value }.index + } - override fun StructureND.mean(): Double = this.fold { it.sum() / tensor.numElements } + override fun StructureND.mean(): Double = sum() / indices.linearSize - override fun StructureND.mean(dim: Int, keepDim: Boolean): DoubleTensor = foldDim(dim, keepDim) { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }.toDoubleTensor() + override fun StructureND.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDimToDouble(dim, keepDim) { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + } - override fun StructureND.std(): Double = fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + override fun StructureND.std(): Double = reduceElements { arr -> + val mean = arr.array.sum() / indices.linearSize + sqrt(arr.array.sumOf { (it - mean) * (it - mean) } / (indices.linearSize - 1)) } - override fun StructureND.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + override fun StructureND.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDimToDouble( dim, keepDim ) { arr -> check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }.toDoubleTensor() - - override fun StructureND.variance(): Double = fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) } - override fun StructureND.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + override fun StructureND.variance(): Double = reduceElements { arr -> + val linearSize = indices.linearSize + val mean = arr.array.sum() / linearSize + arr.array.sumOf { (it - mean) * (it - mean) } / (linearSize - 1) + } + + override fun StructureND.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDimToDouble( dim, keepDim ) { arr -> check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }.toDoubleTensor() + } - private fun cov(x: DoubleTensor, y: DoubleTensor): Double { + private fun cov(x: StructureND, y: StructureND): Double { val n = x.shape[0] return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) } @@ -675,49 +680,55 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( intArrayOf(n, n), - DoubleArray(n * n) { 0.0 } + DoubleBuffer(n * n) { 0.0 } ) for (i in 0 until n) { for (j in 0 until n) { - resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + resTensor[intArrayOf(i, j)] = cov(tensors[i], tensors[j]) } } return resTensor } - override fun StructureND.exp(): DoubleTensor = tensor.map { exp(it) } + override fun StructureND.exp(): DoubleTensor = map { exp(it) } - override fun StructureND.ln(): DoubleTensor = tensor.map { ln(it) } + override fun StructureND.ln(): DoubleTensor = map { ln(it) } - override fun StructureND.sqrt(): DoubleTensor = tensor.map { sqrt(it) } + override fun StructureND.sqrt(): DoubleTensor = map { sqrt(it) } - override fun StructureND.cos(): DoubleTensor = tensor.map { cos(it) } + override fun StructureND.cos(): DoubleTensor = map { cos(it) } - override fun StructureND.acos(): DoubleTensor = tensor.map { acos(it) } + override fun StructureND.acos(): DoubleTensor = map { acos(it) } - override fun StructureND.cosh(): DoubleTensor = tensor.map { cosh(it) } + override fun StructureND.cosh(): DoubleTensor = map { cosh(it) } - override fun StructureND.acosh(): DoubleTensor = tensor.map { acosh(it) } + override fun StructureND.acosh(): DoubleTensor = map { acosh(it) } - override fun StructureND.sin(): DoubleTensor = tensor.map { sin(it) } + override fun StructureND.sin(): DoubleTensor = map { sin(it) } - override fun StructureND.asin(): DoubleTensor = tensor.map { asin(it) } + override fun StructureND.asin(): DoubleTensor = map { asin(it) } - override fun StructureND.sinh(): DoubleTensor = tensor.map { sinh(it) } + override fun StructureND.sinh(): DoubleTensor = map { sinh(it) } - override fun StructureND.asinh(): DoubleTensor = tensor.map { asinh(it) } + override fun StructureND.asinh(): DoubleTensor = map { asinh(it) } - override fun StructureND.tan(): DoubleTensor = tensor.map { tan(it) } + override fun StructureND.tan(): DoubleTensor = map { tan(it) } - override fun StructureND.atan(): DoubleTensor = tensor.map { atan(it) } + override fun StructureND.atan(): DoubleTensor = map { atan(it) } - override fun StructureND.tanh(): DoubleTensor = tensor.map { tanh(it) } + override fun StructureND.tanh(): DoubleTensor = map { tanh(it) } - override fun StructureND.atanh(): DoubleTensor = tensor.map { atanh(it) } + override fun StructureND.atanh(): DoubleTensor = map { atanh(it) } - override fun StructureND.ceil(): DoubleTensor = tensor.map { ceil(it) } + override fun power(arg: StructureND, pow: Number): StructureND = if (pow is Int) { + arg.map { it.pow(pow) } + } else { + arg.map { it.pow(pow.toDouble()) } + } - override fun StructureND.floor(): DoubleTensor = tensor.map { floor(it) } + override fun StructureND.ceil(): DoubleTensor = map { ceil(it) } + + override fun StructureND.floor(): DoubleTensor = map { floor(it) } override fun StructureND.inv(): DoubleTensor = invLU(1e-9) @@ -733,7 +744,7 @@ public open class DoubleTensorAlgebra : * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. */ public fun StructureND.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) + computeLU(this, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") /** @@ -769,18 +780,18 @@ public open class DoubleTensorAlgebra : ) { "Inappropriate shapes of input tensors" } val n = luTensor.shape.last() - val pTensor = luTensor.zeroesLike() + val pTensor = zeroesLike(luTensor) pTensor .matrixSequence() - .zip(pivotsTensor.tensor.vectorSequence()) + .zip(pivotsTensor.asIntTensor().vectorSequence()) .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } - val lTensor = luTensor.zeroesLike() - val uTensor = luTensor.zeroesLike() + val lTensor = zeroesLike(luTensor) + val uTensor = zeroesLike(luTensor) lTensor.matrixSequence() .zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence()) + .zip(luTensor.asDoubleTensor().matrixSequence()) .forEach { (pairLU, lu) -> val (l, u) = pairLU luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) @@ -804,12 +815,12 @@ public open class DoubleTensorAlgebra : */ public fun StructureND.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(tensor, epsilon) + checkPositiveDefinite(asDoubleTensor(), epsilon) val n = shape.last() - val lTensor = zeroesLike() + val lTensor = zeroesLike(this) - for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) + for ((a, l) in asDoubleTensor().matrixSequence().zip(lTensor.matrixSequence())) for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor @@ -819,15 +830,17 @@ public open class DoubleTensorAlgebra : override fun StructureND.qr(): Pair { checkSquareMatrix(shape) - val qTensor = zeroesLike() - val rTensor = zeroesLike() - tensor.matrixSequence() + val qTensor = zeroesLike(this) + val rTensor = zeroesLike(this) + + //TODO replace with cycle + asDoubleTensor().matrixSequence() .zip( (qTensor.matrixSequence() .zip(rTensor.matrixSequence())) ).forEach { (matrix, qr) -> val (q, r) = qr - qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) + qrHelper(matrix, q, r.as2D()) } return qTensor to rTensor @@ -850,14 +863,14 @@ public open class DoubleTensorAlgebra : * @return a triple `Triple(U, S, V)`. */ public fun StructureND.svd(epsilon: Double): Triple { - val size = tensor.dimension - val commonShape = tensor.shape.sliceArray(0 until size - 2) - val (n, m) = tensor.shape.sliceArray(size - 2 until size) + val size = dimension + val commonShape = shape.sliceArray(0 until size - 2) + val (n, m) = shape.sliceArray(size - 2 until size) val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) val sTensor = zeros(commonShape + intArrayOf(min(n, m))) val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - val matrices = tensor.matrices + val matrices: VirtualBuffer = asDoubleTensor().matrices val uTensors = uTensor.matrices val sTensorVectors = sTensor.vectors val vTensors = vTensor.matrices @@ -872,17 +885,16 @@ public open class DoubleTensorAlgebra : val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.mutableBuffer.array() - .slice(matrix.bufferStart until matrix.bufferStart + matrixSize) - .toDoubleArray() + matrix.source.view(0, matrixSize) ) svdHelper(curMatrix, usv, m, n, epsilon) } - return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) + return Triple(uTensor.transposed(), sTensor, vTensor.transposed()) } - override fun StructureND.symEig(): Pair = symEigJacobi(maxIteration = 50, epsilon = 1e-15) + override fun StructureND.symEig(): Pair = + symEigJacobi(maxIteration = 50, epsilon = 1e-15) /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, @@ -893,7 +905,8 @@ public open class DoubleTensorAlgebra : * @return a pair `eigenvalues to eigenvectors`. */ public fun StructureND.symEigSvd(epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) + //TODO optimize conversion + checkSymmetric(asDoubleTensor(), epsilon) fun MutableStructure2D.cleanSym(n: Int) { for (i in 0 until n) { @@ -907,9 +920,9 @@ public open class DoubleTensorAlgebra : } } - val (u, s, v) = tensor.svd(epsilon) + val (u, s, v) = svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = u.transpose() dot v + val utv = u.transposed() matmul v val n = s.shape.last() for (matrix in utv.matrixSequence()) { matrix.as2D().cleanSym(n) @@ -920,7 +933,8 @@ public open class DoubleTensorAlgebra : } public fun StructureND.symEigJacobi(maxIteration: Int, epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) + //TODO optimize conversion + checkSymmetric(asDoubleTensor(), epsilon) val size = this.dimension val eigenvectors = zeros(this.shape) @@ -928,18 +942,18 @@ public open class DoubleTensorAlgebra : var eigenvalueStart = 0 var eigenvectorStart = 0 - for (matrix in tensor.matrixSequence()) { + for (matrix in asDoubleTensor().matrixSequence()) { val matrix2D = matrix.as2D() val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) for (i in 0 until matrix2D.rowNum) { for (j in 0 until matrix2D.colNum) { - eigenvectors.mutableBuffer.array()[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] + eigenvectors.source[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] } } for (i in 0 until matrix2D.rowNum) { - eigenvalues.mutableBuffer.array()[eigenvalueStart + i] = d[i] + eigenvalues.source[eigenvalueStart + i] = d[i] } eigenvalueStart += this.shape.last() @@ -949,121 +963,6 @@ public open class DoubleTensorAlgebra : return eigenvalues to eigenvectors } - private fun MutableStructure2D.jacobiHelper( - maxIteration: Int, - epsilon: Double - ): Pair, Structure2D> { - val n = this.shape[0] - val A_ = this.copy() - val V = eye(n) - val D = DoubleTensor(intArrayOf(n), (0 until this.rowNum).map { this[it, it] }.toDoubleArray()).as1D() - val B = DoubleTensor(intArrayOf(n), (0 until this.rowNum).map { this[it, it] }.toDoubleArray()).as1D() - val Z = zeros(intArrayOf(n)).as1D() - - // assume that buffered tensor is square matrix - operator fun BufferedTensor.get(i: Int, j: Int): Double { - return this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] - } - - operator fun BufferedTensor.set(i: Int, j: Int, value: Double) { - this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] = value - } - - fun maxOffDiagonal(matrix: BufferedTensor): Double { - var maxOffDiagonalElement = 0.0 - for (i in 0 until n - 1) { - for (j in i + 1 until n) { - maxOffDiagonalElement = max(maxOffDiagonalElement, abs(matrix[i, j])) - } - } - return maxOffDiagonalElement - } - - fun rotate(a: BufferedTensor, s: Double, tau: Double, i: Int, j: Int, k: Int, l: Int) { - val g = a[i, j] - val h = a[k, l] - a[i, j] = g - s * (h + g * tau) - a[k, l] = h + s * (g - h * tau) - } - - fun jacobiIteration( - a: BufferedTensor, - v: BufferedTensor, - d: MutableStructure1D, - z: MutableStructure1D, - ) { - for (ip in 0 until n - 1) { - for (iq in ip + 1 until n) { - val g = 100.0 * abs(a[ip, iq]) - - if (g <= epsilon * abs(d[ip]) && g <= epsilon * abs(d[iq])) { - a[ip, iq] = 0.0 - continue - } - - var h = d[iq] - d[ip] - val t = when { - g <= epsilon * abs(h) -> (a[ip, iq]) / h - else -> { - val theta = 0.5 * h / (a[ip, iq]) - val denominator = abs(theta) + sqrt(1.0 + theta * theta) - if (theta < 0.0) -1.0 / denominator else 1.0 / denominator - } - } - - val c = 1.0 / sqrt(1 + t * t) - val s = t * c - val tau = s / (1.0 + c) - h = t * a[ip, iq] - z[ip] -= h - z[iq] += h - d[ip] -= h - d[iq] += h - a[ip, iq] = 0.0 - - for (j in 0 until ip) { - rotate(a, s, tau, j, ip, j, iq) - } - for (j in (ip + 1) until iq) { - rotate(a, s, tau, ip, j, j, iq) - } - for (j in (iq + 1) until n) { - rotate(a, s, tau, ip, j, iq, j) - } - for (j in 0 until n) { - rotate(v, s, tau, j, ip, j, iq) - } - } - } - } - - fun updateDiagonal( - d: MutableStructure1D, - z: MutableStructure1D, - b: MutableStructure1D, - ) { - for (ip in 0 until d.size) { - b[ip] += z[ip] - d[ip] = b[ip] - z[ip] = 0.0 - } - } - - var sm = maxOffDiagonal(A_) - for (iteration in 0 until maxIteration) { - if (sm < epsilon) { - break - } - - jacobiIteration(A_, V, D, Z) - updateDiagonal(D, Z, B) - sm = maxOffDiagonal(A_) - } - - // TODO sort eigenvalues - return D to V.as2D() - } - /** * Computes the determinant of a square matrix input, or of each square matrix in a batched input * using LU factorization algorithm. @@ -1073,15 +972,16 @@ public open class DoubleTensorAlgebra : * @return the determinant. */ public fun StructureND.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() - val pivotsTensor = tensor.setUpPivots() + checkSquareMatrix(shape) + //TODO check for unnecessary copies + val luTensor = copyToTensor() + val pivotsTensor = setUpPivots() val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + val resBuffer = DoubleBuffer(detTensorShape.reduce(Int::times)) { 0.0 } val detTensor = DoubleTensor( detTensorShape, @@ -1107,8 +1007,9 @@ public open class DoubleTensorAlgebra : */ public fun StructureND.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) - val invTensor = luTensor.zeroesLike() + val invTensor = zeroesLike(luTensor) + //TODO replace sequence with a cycle val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) for ((luP, invMatrix) in seq) { val (lu, pivots) = luP @@ -1131,14 +1032,14 @@ public open class DoubleTensorAlgebra : * @return triple of `P`, `L` and `U` tensors. */ public fun StructureND.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = tensor.luFactor(epsilon) + val (lu, pivots) = luFactor(epsilon) return luPivot(lu, pivots) } override fun StructureND.lu(): Triple = lu(1e-9) } -public val Double.Companion.tensorAlgebra: DoubleTensorAlgebra.Companion get() = DoubleTensorAlgebra -public val DoubleField.tensorAlgebra: DoubleTensorAlgebra.Companion get() = DoubleTensorAlgebra +public val Double.Companion.tensorAlgebra: DoubleTensorAlgebra get() = DoubleTensorAlgebra +public val DoubleField.tensorAlgebra: DoubleTensorAlgebra get() = DoubleTensorAlgebra diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt index e3d7c3d35..ed96b6c8f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -1,21 +1,91 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core -import space.kscience.kmath.structures.IntBuffer -import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.structures.* /** * Default [BufferedTensor] implementation for [Int] values */ -public class IntTensor internal constructor( - shape: IntArray, - buffer: IntArray, - offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset){ - public fun asDouble() : DoubleTensor = - DoubleTensor(shape, mutableBuffer.array().map{ it.toDouble()}.toDoubleArray(), bufferStart) +public class OffsetIntBuffer( + private val source: IntBuffer, + private val offset: Int, + override val size: Int, +) : MutableBuffer { + + init { + require(offset >= 0) { "Offset must be non-negative" } + require(size >= 0) { "Size must be non-negative" } + require(offset + size <= source.size) { "Maximum index must be inside source dimension" } + } + + override fun set(index: Int, value: Int) { + require(index in 0 until size) { "Index must be in [0, size)" } + source[index + offset] = value + } + + override fun get(index: Int): Int = source[index + offset] + + /** + * Copy only a part of buffer that belongs to this tensor + */ + override fun copy(): IntBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() + + override fun iterator(): Iterator = iterator { + for (i in indices) { + yield(get(i)) + } + } + + override fun toString(): String = Buffer.toString(this) + + public fun view(addOffset: Int, newSize: Int = size - addOffset): OffsetIntBuffer = + OffsetIntBuffer(source, offset + addOffset, newSize) +} + +public fun OffsetIntBuffer.slice(range: IntRange): OffsetIntBuffer = view(range.first, range.last - range.first) + +/** + * Map only operable content of the offset buffer + */ +public inline fun OffsetIntBuffer.map(operation: (Int) -> Int): IntBuffer = + IntBuffer(size) { operation(get(it)) } + +public inline fun OffsetIntBuffer.zip( + other: OffsetIntBuffer, + operation: (l: Int, r: Int) -> Int, +): IntBuffer { + require(size == other.size) { "The sizes of zipped buffers must be the same" } + return IntBuffer(size) { operation(get(it), other[it]) } +} + +/** + * map in place + */ +public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) { + indices.forEach { set(it, operation(get(it))) } +} + +/** + * Default [BufferedTensor] implementation for [Int] values + */ +public class IntTensor( + shape: IntArray, + override val source: OffsetIntBuffer, +) : BufferedTensor(shape) { + + init { + require(linearSize == source.size) { "Source buffer size must be equal tensor size" } + } + + public constructor(shape: IntArray, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) + + override fun get(index: IntArray): Int = this.source[indices.offset(index)] + + override fun set(index: IntArray, value: Int) { + source[indices.offset(index)] = value + } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt new file mode 100644 index 000000000..124ccc668 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt @@ -0,0 +1,454 @@ +/* + * Copyright 2018-2022 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. + */ + + +@file:OptIn(PerformancePitfall::class) + +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.structures.* +import space.kscience.kmath.tensors.api.* +import space.kscience.kmath.tensors.core.internal.* +import kotlin.math.* + +/** + * Implementation of basic operations over double tensors and basic algebra operations on them. + */ +public open class IntTensorAlgebra : TensorAlgebra { + + public companion object : IntTensorAlgebra() + + override val elementAlgebra: IntRing get() = IntRing + + + /** + * Applies the [transform] function to each element of the tensor and returns the resulting modified tensor. + * + * @param transform the function to be applied to each element of the tensor. + * @return the resulting tensor after applying the function. + */ + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun StructureND.map(transform: IntRing.(Int) -> Int): IntTensor { + val tensor = this.asIntTensor() + //TODO remove additional copy + val array = IntBuffer(tensor.source.size) { IntRing.transform(tensor.source[it]) } + return IntTensor( + tensor.shape, + array, + ) + } + + public inline fun Tensor.mapInPlace(operation: (Int) -> Int) { + if (this is IntTensor) { + source.mapInPlace(operation) + } else { + indices.forEach { set(it, operation(get(it))) } + } + } + + public inline fun Tensor.mapIndexedInPlace(operation: (IntArray, Int) -> Int) { + indices.forEach { set(it, operation(it, get(it))) } + } + + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun StructureND.mapIndexed(transform: IntRing.(index: IntArray, Int) -> Int): IntTensor { + val tensor = this.asIntTensor() + //TODO remove additional copy + val buffer = IntBuffer(tensor.source.size) { + IntRing.transform(tensor.indices.index(it), tensor.source[it]) + } + return IntTensor(tensor.shape, buffer) + } + + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun zip( + left: StructureND, + right: StructureND, + transform: IntRing.(Int, Int) -> Int, + ): IntTensor { + checkShapesCompatible(left, right) + + val leftTensor = left.asIntTensor() + val rightTensor = right.asIntTensor() + val buffer = IntBuffer(leftTensor.source.size) { + IntRing.transform(leftTensor.source[it], rightTensor.source[it]) + } + return IntTensor(leftTensor.shape, buffer) + } + + + public inline fun StructureND.reduceElements(transform: (IntBuffer) -> Int): Int = + transform(asIntTensor().source.copy()) + //TODO do we need protective copy? + + override fun StructureND.valueOrNull(): Int? { + val dt = asIntTensor() + return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + } + + override fun StructureND.value(): Int = valueOrNull() + ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") + + /** + * Constructs a tensor with the specified shape and data. + * + * @param shape the desired shape for the tensor. + * @param array one-dimensional data array. + * @return tensor with the [shape] shape and [array] data. + */ + public fun fromArray(shape: IntArray, array: IntArray): IntTensor { + checkNotEmptyShape(shape) + check(array.isNotEmpty()) { "Illegal empty buffer provided" } + check(array.size == shape.reduce(Int::times)) { + "Inconsistent shape ${shape.toList()} for buffer of size ${array.size} provided" + } + return IntTensor(shape, array.asBuffer()) + } + + /** + * Constructs a tensor with the specified shape and initializer. + * + * @param shape the desired shape for the tensor. + * @param initializer mapping tensor indices to values. + * @return tensor with the [shape] shape and data generated by the [initializer]. + */ + override fun structureND(shape: IntArray, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( + shape, + TensorLinearStructure(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() + ) + + override fun Tensor.getTensor(i: Int): IntTensor { + val dt = asIntTensor() + val lastShape = shape.drop(1).toIntArray() + val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) + return IntTensor(newShape, dt.source.view(newShape.reduce(Int::times) * i)) + } + + /** + * Creates a tensor of a given shape and fills all elements with a given value. + * + * @param value the value to fill the output tensor with. + * @param shape array of integers defining the shape of the output tensor. + * @return tensor with the [shape] shape and filled with [value]. + */ + public fun full(value: Int, shape: IntArray): IntTensor { + checkNotEmptyShape(shape) + val buffer = IntBuffer(shape.reduce(Int::times)) { value } + return IntTensor(shape, buffer) + } + + /** + * Returns a tensor with the same shape as `input` filled with [value]. + * + * @param value the value to fill the output tensor with. + * @return tensor with the `input` tensor shape and filled with [value]. + */ + public fun fullLike(structureND: StructureND<*>, value: Int): IntTensor { + val shape = structureND.shape + val buffer = IntBuffer(structureND.indices.linearSize) { value } + return IntTensor(shape, buffer) + } + + /** + * Returns a tensor filled with the scalar value `0`, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value `0`, with the [shape] shape. + */ + public fun zeros(shape: IntArray): IntTensor = full(0, shape) + + /** + * Returns a tensor filled with the scalar value `0`, with the same shape as a given array. + * + * @return tensor filled with the scalar value `0`, with the same shape as `input` tensor. + */ + public fun zeroesLike(structureND: StructureND): IntTensor = fullLike(structureND.asIntTensor(), 0) + + /** + * Returns a tensor filled with the scalar value `1`, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value `1`, with the [shape] shape. + */ + public fun ones(shape: IntArray): IntTensor = full(1, shape) + + /** + * Returns a tensor filled with the scalar value `1`, with the same shape as a given array. + * + * @return tensor filled with the scalar value `1`, with the same shape as `input` tensor. + */ + public fun onesLike(structureND: Tensor<*>): IntTensor = fullLike(structureND, 1) + + /** + * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. + * + * @param n the number of rows and columns + * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. + */ + public fun eye(n: Int): IntTensor { + val shape = intArrayOf(n, n) + val buffer = IntBuffer(n * n) { 0 } + val res = IntTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1 + } + return res + } + + override fun Int.plus(arg: StructureND): IntTensor = arg.map { this@plus + it } + + override fun StructureND.plus(arg: Int): IntTensor = map { it + arg } + + override fun StructureND.plus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l + r } + + override fun Tensor.plusAssign(value: Int) { + mapInPlace { it + value } + } + + override fun Tensor.plusAssign(arg: StructureND) { + checkShapesCompatible(asIntTensor(), arg.asIntTensor()) + mapIndexedInPlace { index, value -> + value + arg[index] + } + } + + override fun Int.minus(arg: StructureND): IntTensor = arg.map { this@minus - it } + + override fun StructureND.minus(arg: Int): IntTensor = map { it - arg } + + override fun StructureND.minus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l - r } + + override fun Tensor.minusAssign(value: Int) { + mapInPlace { it - value } + } + + override fun Tensor.minusAssign(arg: StructureND) { + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value - arg[index] } + } + + override fun Int.times(arg: StructureND): IntTensor = arg.map { this@times * it } + + override fun StructureND.times(arg: Int): IntTensor = arg * asIntTensor() + + override fun StructureND.times(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l * r } + + override fun Tensor.timesAssign(value: Int) { + mapInPlace { it * value } + } + + override fun Tensor.timesAssign(arg: StructureND) { + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value * arg[index] } + } + + override fun StructureND.unaryMinus(): IntTensor = map { -it } + + override fun Tensor.transposed(i: Int, j: Int): IntTensor { + // TODO change strides instead of changing content + val dt = asIntTensor() + val ii = dt.minusIndex(i) + val jj = dt.minusIndex(j) + checkTranspose(dt.dimension, ii, jj) + val n = dt.linearSize + val resBuffer = IntArray(n) + + val resShape = dt.shape.copyOf() + resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } + + val resTensor = IntTensor(resShape, resBuffer.asBuffer()) + + for (offset in 0 until n) { + val oldMultiIndex = dt.indices.index(offset) + val newMultiIndex = oldMultiIndex.copyOf() + newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } + + val linearIndex = resTensor.indices.offset(newMultiIndex) + resTensor.source[linearIndex] = dt.source[offset] + } + return resTensor + } + + override fun Tensor.view(shape: IntArray): IntTensor { + checkView(asIntTensor(), shape) + return IntTensor(shape, asIntTensor().source) + } + + override fun Tensor.viewAs(other: StructureND): IntTensor = + view(other.shape) + + override fun StructureND.dot(other: StructureND): IntTensor { + TODO("not implemented for integers") + } + + override fun diagonalEmbedding( + diagonalEntries: Tensor, + offset: Int, + dim1: Int, + dim2: Int, + ): IntTensor { + val n = diagonalEntries.shape.size + val d1 = minusIndexFrom(n + 1, dim1) + val d2 = minusIndexFrom(n + 1, dim2) + + check(d1 != d2) { + "Diagonal dimensions cannot be identical $d1, $d2" + } + check(d1 <= n && d2 <= n) { + "Dimension out of range" + } + + var lessDim = d1 + var greaterDim = d2 + var realOffset = offset + if (lessDim > greaterDim) { + realOffset *= -1 + lessDim = greaterDim.also { greaterDim = lessDim } + } + + val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + val resTensor = zeros(resShape) + + for (i in 0 until diagonalEntries.asIntTensor().linearSize) { + val multiIndex = diagonalEntries.asIntTensor().indices.index(i) + + var offset1 = 0 + var offset2 = abs(realOffset) + if (realOffset < 0) { + offset1 = offset2.also { offset2 = offset1 } + } + val diagonalMultiIndex = multiIndex.slice(0 until lessDim).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset1) + + multiIndex.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset2) + + multiIndex.slice(greaterDim - 1 until n - 1).toIntArray() + + resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] + } + + return resTensor.asIntTensor() + } + + /** + * Compares element-wise two int tensors + * + * @param other the tensor to compare with `input` tensor. + * @param epsilon permissible error when comparing two Int values. + * @return true if two tensors have the same shape and elements, false otherwise. + */ + public fun Tensor.eq(other: Tensor): Boolean = + asIntTensor().eq(other) { x, y -> x == y } + + private fun Tensor.eq( + other: Tensor, + eqFunction: (Int, Int) -> Boolean, + ): Boolean { + checkShapesCompatible(asIntTensor(), other) + val n = asIntTensor().linearSize + if (n != other.asIntTensor().linearSize) { + return false + } + for (i in 0 until n) { + if (!eqFunction(asIntTensor().source[i], other.asIntTensor().source[i])) { + return false + } + } + return true + } + + /** + * Concatenates a sequence of tensors with equal shapes along the first dimension. + * + * @param tensors the [List] of tensors with same shapes to concatenate + * @return tensor with concatenation result + */ + public fun stack(tensors: List>): IntTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val shape = tensors[0].shape + check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } + val resShape = intArrayOf(tensors.size) + shape +// val resBuffer: List = tensors.flatMap { +// it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart) +// .take(it.asIntTensor().linearSize) +// } + val resBuffer = tensors.map { it.asIntTensor().source }.concat() + return IntTensor(resShape, resBuffer) + } + + /** + * Builds tensor from rows of the input tensor. + * + * @param indices the [IntArray] of 1-dimensional indices + * @return tensor with rows corresponding to row by [indices] + */ + public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { getTensor(it) }) + + private inline fun StructureND.foldDimToInt( + dim: Int, + keepDim: Boolean, + foldFunction: (IntArray) -> Int, + ): IntTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val init = foldFunction(IntArray(1) { 0 }) + val resTensor = IntTensor( + resShape, + IntBuffer(resNumElements) { init } + ) + for (index in resTensor.indices) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(IntArray(shape[dim]) { i -> + asIntTensor()[prefix + intArrayOf(i) + suffix] + }) + } + return resTensor + } + + + override fun StructureND.sum(): Int = reduceElements { it.array.sum() } + + override fun StructureND.sum(dim: Int, keepDim: Boolean): IntTensor = + foldDimToInt(dim, keepDim) { x -> x.sum() } + + override fun StructureND.min(): Int = reduceElements { it.array.min() } + + override fun StructureND.min(dim: Int, keepDim: Boolean): IntTensor = + foldDimToInt(dim, keepDim) { x -> x.minOrNull()!! } + + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDimToInt(dim, keepDim) { x -> + x.withIndex().minBy { it.value }.index + } + + override fun StructureND.max(): Int = reduceElements { it.array.max() } + + override fun StructureND.max(dim: Int, keepDim: Boolean): IntTensor = + foldDimToInt(dim, keepDim) { x -> x.max() } + + + override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = + foldDimToInt(dim, keepDim) { x -> + x.withIndex().maxBy { it.value }.index + } + + public fun StructureND.mean(): Double = sum().toDouble() / indices.linearSize +} + +public val Int.Companion.tensorAlgebra: IntTensorAlgebra get() = IntTensorAlgebra +public val IntRing.tensorAlgebra: IntTensorAlgebra get() = IntTensorAlgebra + + diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt index 19eefc2f8..729fc0d13 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -15,14 +15,12 @@ import kotlin.math.max * @param shape the shape of the tensor. */ public class TensorLinearStructure(override val shape: IntArray) : Strides() { - override val strides: IntArray - get() = stridesFromShape(shape) + override val strides: IntArray get() = stridesFromShape(shape) override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - override val linearSize: Int - get() = shape.reduce(Int::times) + override val linearSize: Int get() = linearSizeOf(shape) override fun equals(other: Any?): Boolean { if (this === other) return true @@ -41,6 +39,8 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides() { public companion object { + public fun linearSizeOf(shape: IntArray): Int = shape.reduce(Int::times) + public fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt index 9d37423e5..fee62c79c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -1,10 +1,11 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core.internal +import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.max @@ -24,8 +25,8 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } val curLinearIndex = tensor.indices.offset(curMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex] + resTensor.source[linearIndex] = + tensor.source[curLinearIndex] } } @@ -63,7 +64,7 @@ internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor } val n = newShape.reduce { acc, i -> acc * i } - val resTensor = DoubleTensor(newShape, DoubleArray(n)) + val resTensor = DoubleTensor(newShape, DoubleArray(n).asBuffer()) for (i in tensor.shape.indices) { val curDim = tensor.shape[i] @@ -82,7 +83,7 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val n = totalShape.reduce { acc, i -> acc * i } return tensors.map { tensor -> - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape, DoubleArray(n).asBuffer()) multiIndexBroadCasting(tensor, resTensor, n) resTensor } @@ -106,17 +107,17 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List checkShapesCompatible(a: StructureND, b: StructureND) = +@PublishedApi +internal fun checkShapesCompatible(a: StructureND, b: StructureND): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } @@ -50,16 +51,15 @@ internal fun checkSquareMatrix(shape: IntArray) { } internal fun DoubleTensorAlgebra.checkSymmetric( - tensor: Tensor, epsilon: Double = 1e-6 -) = - check(tensor.eq(tensor.transpose(), epsilon)) { - "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" - } + tensor: Tensor, epsilon: Double = 1e-6, +) = check(tensor.eq(tensor.transposed(), epsilon)) { + "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" +} internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + check(mat.asDoubleTensor().detLU().value() > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asDoubleTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt new file mode 100644 index 000000000..c5910a436 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt @@ -0,0 +1,188 @@ +/* + * Copyright 2018-2022 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.tensors.core.internal + +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.nd.get +import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.eye +import kotlin.math.abs +import kotlin.math.max +import kotlin.math.sqrt + + +internal fun MutableStructure2D.jacobiHelper( + maxIteration: Int, + epsilon: Double, +): Pair> { + val n = rowNum + val A_ = copyToTensor() + val V = eye(n) + val D = DoubleBuffer(n) { get(it, it) } + val B = DoubleBuffer(n) { get(it, it) } + val Z = DoubleBuffer(n) { 0.0 } + + // assume that buffered tensor is square matrix + operator fun DoubleTensor.get(i: Int, j: Int): Double { + return source[i * shape[0] + j] + } + + operator fun BufferedTensor.set(i: Int, j: Int, value: Double) { + source[i * shape[0] + j] = value + } + + fun maxOffDiagonal(matrix: BufferedTensor): Double { + var maxOffDiagonalElement = 0.0 + for (i in 0 until n - 1) { + for (j in i + 1 until n) { + maxOffDiagonalElement = max(maxOffDiagonalElement, abs(matrix[i, j])) + } + } + return maxOffDiagonalElement + } + + fun rotate(a: BufferedTensor, s: Double, tau: Double, i: Int, j: Int, k: Int, l: Int) { + val g = a[i, j] + val h = a[k, l] + a[i, j] = g - s * (h + g * tau) + a[k, l] = h + s * (g - h * tau) + } + + fun jacobiIteration( + a: BufferedTensor, + v: BufferedTensor, + d: DoubleBuffer, + z: DoubleBuffer, + ) { + for (ip in 0 until n - 1) { + for (iq in ip + 1 until n) { + val g = 100.0 * abs(a[ip, iq]) + + if (g <= epsilon * abs(d[ip]) && g <= epsilon * abs(d[iq])) { + a[ip, iq] = 0.0 + continue + } + + var h = d[iq] - d[ip] + val t = when { + g <= epsilon * abs(h) -> (a[ip, iq]) / h + else -> { + val theta = 0.5 * h / (a[ip, iq]) + val denominator = abs(theta) + sqrt(1.0 + theta * theta) + if (theta < 0.0) -1.0 / denominator else 1.0 / denominator + } + } + + val c = 1.0 / sqrt(1 + t * t) + val s = t * c + val tau = s / (1.0 + c) + h = t * a[ip, iq] + z[ip] -= h + z[iq] += h + d[ip] -= h + d[iq] += h + a[ip, iq] = 0.0 + + for (j in 0 until ip) { + rotate(a, s, tau, j, ip, j, iq) + } + for (j in (ip + 1) until iq) { + rotate(a, s, tau, ip, j, j, iq) + } + for (j in (iq + 1) until n) { + rotate(a, s, tau, ip, j, iq, j) + } + for (j in 0 until n) { + rotate(v, s, tau, j, ip, j, iq) + } + } + } + } + + fun updateDiagonal( + d: DoubleBuffer, + z: DoubleBuffer, + b: DoubleBuffer, + ) { + for (ip in 0 until d.size) { + b[ip] += z[ip] + d[ip] = b[ip] + z[ip] = 0.0 + } + } + + var sm = maxOffDiagonal(A_) + for (iteration in 0 until maxIteration) { + if (sm < epsilon) { + break + } + + jacobiIteration(A_, V, D, Z) + updateDiagonal(D, Z, B) + sm = maxOffDiagonal(A_) + } + + // TODO sort eigenvalues + return D to V.as2D() +} + +/** + * Concatenate a list of arrays + */ +internal fun List.concat(): DoubleBuffer { + val array = DoubleArray(sumOf { it.size }) + var pointer = 0 + while (pointer < array.size) { + for (bufferIndex in indices) { + val buffer = get(bufferIndex) + for (innerIndex in buffer.indices) { + array[pointer] = buffer[innerIndex] + pointer++ + } + } + } + return array.asBuffer() +} + +internal val DoubleTensor.vectors: VirtualBuffer + get() { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + + return VirtualBuffer(linearSize / vectorOffset) { index -> + val offset = index * vectorOffset + DoubleTensor(vectorShape, source.view(offset, vectorShape.first())) + } + } + + +internal fun DoubleTensor.vectorSequence(): Sequence = vectors.asSequence() + + +internal val DoubleTensor.matrices: VirtualBuffer + get() { + val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + + val size = TensorLinearStructure.linearSizeOf(matrixShape) + + return VirtualBuffer(linearSize / matrixOffset) { index -> + val offset = index * matrixOffset + DoubleTensor(matrixShape, source.view(offset, size)) + } + } + +internal fun DoubleTensor.matrixSequence(): Sequence = matrices.asSequence() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt new file mode 100644 index 000000000..db289a090 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2018-2022 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.tensors.core.internal + +import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.structures.IntBuffer +import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.IntTensor +import space.kscience.kmath.tensors.core.OffsetIntBuffer + +/** + * Concatenate a list of arrays + */ +internal fun List.concat(): IntBuffer { + val array = IntArray(sumOf { it.size }) + var pointer = 0 + while (pointer < array.size) { + for (bufferIndex in indices) { + val buffer = get(bufferIndex) + for (innerIndex in buffer.indices) { + array[pointer] = buffer[innerIndex] + pointer++ + } + } + } + return array.asBuffer() +} + + +internal val IntTensor.vectors: VirtualBuffer + get() { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + + return VirtualBuffer(linearSize / vectorOffset) { index -> + val offset = index * vectorOffset + IntTensor(vectorShape, source.view(offset, vectorShape.first())) + } + } + + +internal fun IntTensor.vectorSequence(): Sequence = vectors.asSequence() + + +internal val IntTensor.matrices: VirtualBuffer + get(){ + val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + + return VirtualBuffer(linearSize / matrixOffset) { index -> + val offset = index * matrixOffset + IntTensor(matrixShape, source.view(offset)) + } + } + +internal fun IntTensor.matrixSequence(): Sequence = matrices.asSequence() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index aba6167ce..9047ba29e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -1,79 +1,37 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core.internal -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.tensors.core.BufferedTensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.DoubleTensorAlgebra -import space.kscience.kmath.tensors.core.IntTensor +import space.kscience.kmath.structures.IntBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.* import kotlin.math.abs import kotlin.math.min import kotlin.math.sqrt -internal val BufferedTensor.vectors: VirtualBuffer> - get() { - val n = shape.size - val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) - - return VirtualBuffer(numElements / vectorOffset) { index -> - val offset = index * vectorOffset - BufferedTensor(vectorShape, mutableBuffer, bufferStart + offset) - } - } - - -internal fun BufferedTensor.vectorSequence(): Sequence> = vectors.asSequence() - -/** - * A random access alternative to [matrixSequence] - */ -internal val BufferedTensor.matrices: VirtualBuffer> - get() { - val n = shape.size - check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } - val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - - return VirtualBuffer(numElements / matrixOffset) { index -> - val offset = index * matrixOffset - BufferedTensor(matrixShape, mutableBuffer, bufferStart + offset) - } - } - -internal fun BufferedTensor.matrixSequence(): Sequence> = matrices.asSequence() - internal fun dotTo( a: BufferedTensor, b: BufferedTensor, res: BufferedTensor, l: Int, m: Int, n: Int, ) { - val aStart = a.bufferStart - val bStart = b.bufferStart - val resStart = res.bufferStart - - val aBuffer = a.mutableBuffer - val bBuffer = b.mutableBuffer - val resBuffer = res.mutableBuffer + val aBuffer = a.source + val bBuffer = b.source + val resBuffer = res.source for (i in 0 until l) { for (j in 0 until n) { var curr = 0.0 for (k in 0 until m) { - curr += aBuffer[aStart + i * m + k] * bBuffer[bStart + k * n + j] + curr += aBuffer[i * m + k] * bBuffer[k * n + j] } - resBuffer[resStart + i * n + j] = curr + resBuffer[i * n + j] = curr } } } @@ -129,7 +87,7 @@ internal fun luHelper( return false } -internal fun BufferedTensor.setUpPivots(): IntTensor { +internal fun StructureND.setUpPivots(): IntTensor { val n = this.shape.size val m = this.shape.last() val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } @@ -137,17 +95,17 @@ internal fun BufferedTensor.setUpPivots(): IntTensor { return IntTensor( pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } + IntBuffer(pivotsShape.reduce(Int::times)) { 0 } ) } internal fun DoubleTensorAlgebra.computeLU( - tensor: DoubleTensor, + tensor: StructureND, epsilon: Double, ): Pair? { checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() + val luTensor = tensor.copyToTensor() val pivotsTensor = tensor.setUpPivots() for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) @@ -253,17 +211,17 @@ internal fun DoubleTensorAlgebra.qrHelper( checkSquareMatrix(matrix.shape) val n = matrix.shape[0] val qM = q.as2D() - val matrixT = matrix.transpose(0, 1) - val qT = q.transpose(0, 1) + val matrixT = matrix.transposed(0, 1) + val qT = q.transposed(0, 1) for (j in 0 until n) { - val v = matrixT[j] + val v = matrixT.getTensor(j) val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).value() + r[i, j] = (qT.getTensor(i) dot matrixT.getTensor(j)).value() for (k in 0 until n) { - val qTi = qT[i].as1D() + val qTi = qT.getTensor(i).as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } @@ -280,10 +238,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) var v: DoubleTensor val b: DoubleTensor if (n > m) { - b = a.transpose(0, 1).dot(a) + b = a.transposed(0, 1).dot(a) v = DoubleTensor(intArrayOf(m), getRandomUnitVector(m, 0)) } else { - b = a.dot(a.transpose(0, 1)) + b = a.dot(a.transposed(0, 1)) v = DoubleTensor(intArrayOf(n), getRandomUnitVector(n, 0)) } @@ -308,15 +266,15 @@ internal fun DoubleTensorAlgebra.svdHelper( val (matrixU, matrixS, matrixV) = USV for (k in 0 until min(n, m)) { - var a = matrix.copy() + var a = matrix.copyToTensor() for ((singularValue, u, v) in res.slice(0 until k)) { val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + outerProduct[i * v.shape[0] + j] = u.getTensor(i).value() * v.getTensor(j).value() } } - a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct.asBuffer())) } var v: DoubleTensor var u: DoubleTensor @@ -328,7 +286,7 @@ internal fun DoubleTensorAlgebra.svdHelper( u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) - v = matrix.transpose(0, 1).dot(u) + v = matrix.transposed(0, 1).dot(u) norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } @@ -337,15 +295,15 @@ internal fun DoubleTensorAlgebra.svdHelper( } val s = res.map { it.first }.toDoubleArray() - val uBuffer = res.map { it.second }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray() - val vBuffer = res.map { it.third }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray() + val uBuffer = res.map { it.second.source }.concat() + val vBuffer = res.map { it.third.source }.concat() for (i in uBuffer.indices) { - matrixU.mutableBuffer.array()[matrixU.bufferStart + i] = uBuffer[i] + matrixU.source[i] = uBuffer[i] } for (i in s.indices) { - matrixS.mutableBuffer.array()[matrixS.bufferStart + i] = s[i] + matrixS.source[i] = s[i] } for (i in vBuffer.indices) { - matrixV.mutableBuffer.array()[matrixV.bufferStart + i] = vBuffer[i] + matrixV.source[i] = vBuffer[i] } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt deleted file mode 100644 index a5cdb2f47..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.tensors.core.internal - -import space.kscience.kmath.nd.MutableBufferND -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.structures.asMutableBuffer -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.BufferedTensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.IntTensor -import space.kscience.kmath.tensors.core.TensorLinearStructure - -internal fun BufferedTensor.asTensor(): IntTensor = - IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun BufferedTensor.asTensor(): DoubleTensor = - DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun StructureND.copyToBufferedTensor(): BufferedTensor = - BufferedTensor( - this.shape, - TensorLinearStructure(this.shape).asSequence().map(this::get).toMutableList().asMutableBuffer(), 0 - ) - -internal fun StructureND.toBufferedTensor(): BufferedTensor = when (this) { - is BufferedTensor -> this - is MutableBufferND -> if (this.indices == TensorLinearStructure(this.shape)) { - BufferedTensor(this.shape, this.buffer, 0) - } else { - this.copyToBufferedTensor() - } - else -> this.copyToBufferedTensor() -} - -@PublishedApi -internal val StructureND.tensor: DoubleTensor - get() = when (this) { - is DoubleTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -internal val Tensor.tensor: IntTensor - get() = when (this) { - is IntTensor -> this - else -> this.toBufferedTensor().asTensor() - } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt index 85cc91b1d..daafdaa58 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt @@ -1,46 +1,30 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core.internal import space.kscience.kmath.nd.as1D +import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.operations.toMutableList import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.* -/** - * Returns a reference to [IntArray] containing all the elements of this [Buffer] or copy the data. - */ -internal fun Buffer.array(): IntArray = when (this) { - is IntBuffer -> array - else -> this.toIntArray() -} - -/** - * Returns a reference to [DoubleArray] containing all the elements of this [Buffer] or copy the data. - */ -@PublishedApi -internal fun Buffer.array(): DoubleArray = when (this) { - is DoubleBuffer -> array - else -> this.toDoubleArray() -} - -internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { +internal fun getRandomNormals(n: Int, seed: Long): DoubleBuffer { val distribution = GaussianSampler(0.0, 1.0) val generator = RandomGenerator.default(seed) - return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() + return distribution.sample(generator).nextBufferBlocking(n) } -internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { - val unnorm = getRandomNormals(n, seed) - val norm = sqrt(unnorm.sumOf { it * it }) - return unnorm.map { it / norm }.toDoubleArray() +internal fun getRandomUnitVector(n: Int, seed: Long): DoubleBuffer { + val unnorm: DoubleBuffer = getRandomNormals(n, seed) + val norm = sqrt(unnorm.array.sumOf { it * it }) + return unnorm.map { it / norm } } internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { @@ -71,6 +55,7 @@ internal fun format(value: Double, digits: Int = 4): String = buildString { append("e+") append(order) } + else -> { append('e') append(order) @@ -116,7 +101,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { } offset += vectorSize - if (this@toPrettyString.numElements == offset) { + if (this@toPrettyString.linearSize == offset) { break } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt index d8e8df31e..619d5c753 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -13,7 +13,10 @@ import kotlin.jvm.JvmName @JvmName("varArgOne") public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(intArrayOf(*shape)) + public fun DoubleTensorAlgebra.one(shape: Shape): DoubleTensor = ones(shape) + @JvmName("varArgZero") public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(intArrayOf(*shape)) -public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) \ No newline at end of file + +public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt deleted file mode 100644 index 5dc8114dd..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.tensors.core - -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.tensor - -/** - * Casts [Tensor] of [Double] to [DoubleTensor] - */ -public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor - -/** - * Casts [Tensor] of [Int] to [IntTensor] - */ -public fun Tensor.toIntTensor(): IntTensor = this.tensor - -/** - * Returns a copy-protected [DoubleArray] of tensor elements - */ -public fun DoubleTensor.copyArray(): DoubleArray { - //TODO use ArrayCopy - return DoubleArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} - -/** - * Returns a copy-protected [IntArray] of tensor elements - */ -public fun IntTensor.copyArray(): IntArray { - return IntArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt new file mode 100644 index 000000000..118624440 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2018-2022 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.tensors.core + +import space.kscience.kmath.nd.DoubleBufferND +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.tensors.api.Tensor + + +/** + * Create a mutable copy of given [StructureND]. + */ +public fun StructureND.copyToTensor(): DoubleTensor = if (this is DoubleTensor) { + DoubleTensor(shape, source.copy()) +} else if (this is DoubleBufferND && indices is TensorLinearStructure) { + DoubleTensor(shape, buffer.copy()) +} else { + DoubleTensor( + shape, + TensorLinearStructure(this.shape).map(this::get).toDoubleArray().asBuffer(), + ) +} + +public fun StructureND.toDoubleTensor(): DoubleTensor { + return if (this is IntTensor) { + DoubleTensor( + shape, + DoubleBuffer(linearSize) { source[it].toDouble() } + ) + } else { + val tensor = DoubleTensorAlgebra.zeroesLike(this) + indices.forEach { + tensor[it] = get(it).toDouble() + } + return tensor + } +} + +/** + * Transforms [StructureND] of [Double] to [DoubleTensor]. Zero copy if possible, but is not guaranteed + */ +public fun StructureND.asDoubleTensor(): DoubleTensor = if (this is DoubleTensor) { + this +} else if (this is DoubleBufferND && indices is TensorLinearStructure) { + DoubleTensor(shape, buffer) +} else { + copyToTensor() +} + +/** + * Casts [Tensor] of [Int] to [IntTensor] + */ +public fun StructureND.asIntTensor(): IntTensor = when (this) { + is IntTensor -> this + else -> IntTensor( + this.shape, + TensorLinearStructure(this.shape).map(this::get).toIntArray().asBuffer() + ) +} \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 6788ae792..6a99b9ba8 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,12 +1,15 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.* +import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors +import space.kscience.kmath.tensors.core.internal.broadcastShapes +import space.kscience.kmath.tensors.core.internal.broadcastTensors +import space.kscience.kmath.tensors.core.internal.broadcastTo import kotlin.test.Test import kotlin.test.assertTrue @@ -34,7 +37,7 @@ internal class TestBroadcasting { val res = broadcastTo(tensor2, tensor1.shape) assertTrue(res.shape contentEquals intArrayOf(2, 3)) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) } @Test @@ -49,9 +52,9 @@ internal class TestBroadcasting { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].source contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -66,15 +69,15 @@ internal class TestBroadcasting { assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1)) - assertTrue(res[0].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0)) - assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0)) + assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0)) + assertTrue(res[2].source contentEquals doubleArrayOf(500.0)) } @Test fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) - val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) + val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) + val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) @@ -95,16 +98,16 @@ internal class TestBroadcasting { val tensor32 = tensor3 - tensor2 assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) - assertTrue(tensor21.mutableBuffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue(tensor21.source contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue(tensor31.shape contentEquals intArrayOf(1, 2, 3)) assertTrue( - tensor31.mutableBuffer.array() + tensor31.source contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) ) assertTrue(tensor32.shape contentEquals intArrayOf(1, 1, 3)) - assertTrue(tensor32.mutableBuffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue(tensor32.source contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 1e21379b4..4bc2e3bdb 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,11 +1,12 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.asBuffer import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue @@ -20,14 +21,14 @@ internal class TestDoubleAnalyticTensorAlgebra { 3.23, 133.7, 25.3, 100.3, 11.0, 12.012 ) - val tensor = DoubleTensor(shape, buffer) + val tensor = DoubleTensor(shape, buffer.asBuffer()) fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { return this.map(transform).toDoubleArray() } fun expectedTensor(transform: (Double) -> Double): DoubleTensor { - return DoubleTensor(shape, buffer.fmap(transform)) + return DoubleTensor(shape, buffer.fmap(transform).asBuffer()) } @Test @@ -106,58 +107,74 @@ internal class TestDoubleAnalyticTensorAlgebra { 1.0, 2.0, -3.0, 4.0 ) - val tensor2 = DoubleTensor(shape2, buffer2) + val tensor2 = DoubleTensor(shape2, buffer2.asBuffer()) @Test fun testMin() = DoubleTensorAlgebra { assertTrue { tensor2.min() == -3.0 } - assertTrue { tensor2.min(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-3.0, 2.0) - )} - assertTrue { tensor2.min(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(1.0, -3.0) - )} + assertTrue { + tensor2.min(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-3.0, 2.0) + ) + } + assertTrue { + tensor2.min(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.0, -3.0) + ) + } } @Test fun testMax() = DoubleTensorAlgebra { assertTrue { tensor2.max() == 4.0 } - assertTrue { tensor2.max(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(1.0, 4.0) - )} - assertTrue { tensor2.max(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(2.0, 4.0) - )} + assertTrue { + tensor2.max(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(1.0, 4.0) + ) + } + assertTrue { + tensor2.max(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(2.0, 4.0) + ) + } } @Test fun testSum() = DoubleTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } - assertTrue { tensor2.sum(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-2.0, 6.0) - )} - assertTrue { tensor2.sum(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(3.0, 1.0) - )} + assertTrue { + tensor2.sum(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-2.0, 6.0) + ) + } + assertTrue { + tensor2.sum(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(3.0, 1.0) + ) + } } @Test fun testMean() = DoubleTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } - assertTrue { tensor2.mean(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-1.0, 3.0) - )} - assertTrue { tensor2.mean(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(1.5, 0.5) - )} + assertTrue { + tensor2.mean(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-1.0, 3.0) + ) + } + assertTrue { + tensor2.mean(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.5, 0.5) + ) + } } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index e025d4b71..1c23cff18 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,12 +1,11 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs import kotlin.test.Test @@ -115,7 +114,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } - assertTrue((q dot r).eq(tensor)) + assertTrue((q matmul r).eq(tensor)) } @@ -136,17 +135,17 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { l.shape contentEquals shape } assertTrue { u.shape contentEquals shape } - assertTrue((p dot tensor).eq(l dot u)) + assertTrue((p matmul tensor).eq(l matmul u)) } @Test fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) - val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( + val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() - val sigmChol = low dot low.transpose() + val sigmChol = low matmul low.transposed() assertTrue(sigma.eq(sigmChol)) } @@ -157,12 +156,12 @@ internal class TestDoubleLinearOpsTensorAlgebra { val res = svd1d(tensor2) assertTrue(res.shape contentEquals intArrayOf(2)) - assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart]) - 0.386) < 0.01 } - assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 } + assertTrue { abs(abs(res.source[0]) - 0.386) < 0.01 } + assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 } } @Test - fun testSVD() = DoubleTensorAlgebra{ + fun testSVD() = DoubleTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @@ -171,16 +170,16 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) + val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) } @Test fun testBatchedSymEig() = DoubleTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) - val tensorSigma = tensor + tensor.transpose() + val tensorSigma = tensor + tensor.transposed() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) + val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } @@ -194,7 +193,7 @@ private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double val tensorSVD = svd.first .dot( diagonalEmbedding(svd.second) - .dot(svd.third.transpose()) + .dot(svd.third.transposed()) ) assertTrue(tensor.eq(tensorSVD, epsilon)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d808637c7..c87cf2a68 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,22 +1,16 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.MutableBufferND -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.tensors.core.internal.array -import space.kscience.kmath.tensors.core.internal.asTensor import space.kscience.kmath.tensors.core.internal.matrixSequence -import space.kscience.kmath.tensors.core.internal.toBufferedTensor import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -36,17 +30,18 @@ internal class TestDoubleTensor { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( - tensor.elements().map { it.second }.toList().toDoubleArray() contentEquals tensor.mutableBuffer.toDoubleArray() + tensor.elements().map { it.second }.toList() + .toDoubleArray() contentEquals tensor.source.toDoubleArray() ) } @Test fun testGet() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) - val matrix = tensor[0].as2D() + val matrix = tensor.getTensor(0).as2D() assertEquals(matrix[0, 1], 5.8) - val vector = tensor[0][1].as1D() + val vector = tensor.getTensor(0, 1).as1D() assertEquals(vector[0], 58.4) matrix[0, 1] = 77.89 @@ -56,9 +51,9 @@ internal class TestDoubleTensor { assertEquals(tensor[intArrayOf(0, 1, 0)], 109.56) tensor.matrixSequence().forEach { - val a = it.asTensor() - val secondRow = a[1].as1D() - val secondColumn = a.transpose(0, 1)[1].as1D() + val a = it.asDoubleTensor() + val secondRow = a.getTensor(1).as1D() + val secondColumn = a.transposed(0, 1).getTensor(1).as1D() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } @@ -68,28 +63,28 @@ internal class TestDoubleTensor { fun testNoBufferProtocol() { // create buffer - val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) + val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(DefaultStrides(intArrayOf(3)), doubleArray) // map to tensors - val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied - val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again + val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. - val tensorArrayPublic = ndArray.toDoubleTensor() // public API, data copied twice - val sharedTensorArray = tensorArrayPublic.toDoubleTensor() // no data copied by matching type + //protective copy + val tensorArrayPublic = ndArray.copyToTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.asDoubleTensor() // no data copied by matching type - assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array()) + assertTrue(tensorArray.source contentEquals sharedTensorArray.source) tensorArray[intArrayOf(0)] = 55.9 assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0) - tensorArrayPublic[intArrayOf(0)] = 55.9 - assertEquals(sharedTensorArray[intArrayOf(0)], 55.9) - assertEquals(bufferedTensorArray[intArrayOf(0)], 1.0) + tensorArrayPublic[intArrayOf(0)] = 57.9 + assertEquals(sharedTensorArray[intArrayOf(0)], 57.9) + assertEquals(tensorArray[intArrayOf(0)], 55.9) - bufferedTensorArray[intArrayOf(0)] = 55.9 + tensorArray[intArrayOf(0)] = 55.9 assertEquals(ndArray[intArrayOf(0)], 1.0) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 205ae2fee..67bebb9a7 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,14 +1,16 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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.tensors.core +import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -18,55 +20,55 @@ internal class TestDoubleTensorAlgebra { fun testDoublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) + assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0)) } @Test fun testDoubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) - val res = 2.0/tensor - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) + val res = 2.0 / tensor + assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5)) } @Test fun testDivDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) + assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0)) } @Test fun testTranspose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) - val res = tensor.transpose(0, 0) + val res = tensor.transposed(0, 0) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(0.0)) + assertTrue(res.source contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @Test fun testTranspose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res = tensor.transpose(1, 0) + val res = tensor.transposed(1, 0) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.source contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @Test fun testTranspose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(-3, 2) - val res12 = tensor.transpose() + val res01 = tensor.transposed(0, 1) + val res02 = tensor.transposed(-3, 2) + val res12 = tensor.transposed() assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -97,8 +99,8 @@ internal class TestDoubleTensorAlgebra { assignResult += tensorC assignResult += -39.4 - assertTrue(expected.mutableBuffer.array() contentEquals result.mutableBuffer.array()) - assertTrue(expected.mutableBuffer.array() contentEquals assignResult.mutableBuffer.array()) + assertBufferEquals(expected.source, result.source) + assertBufferEquals(expected.source, assignResult.source) } @Test @@ -111,26 +113,28 @@ internal class TestDoubleTensorAlgebra { val tensor5 = fromArray(intArrayOf(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) val res12 = tensor1.dot(tensor2) - assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(140.0, 320.0)) + assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0)) assertTrue(res12.shape contentEquals intArrayOf(2)) - val res32 = tensor3.dot(tensor2) - assertTrue(res32.mutableBuffer.array() contentEquals doubleArrayOf(-140.0)) + val res32 = tensor3.matmul(tensor2) + assertTrue(res32.source contentEquals doubleArrayOf(-140.0)) assertTrue(res32.shape contentEquals intArrayOf(1, 1)) val res22 = tensor2.dot(tensor2) - assertTrue(res22.mutableBuffer.array() contentEquals doubleArrayOf(1400.0)) + assertTrue(res22.source contentEquals doubleArrayOf(1400.0)) assertTrue(res22.shape contentEquals intArrayOf(1)) val res11 = tensor1.dot(tensor11) - assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) + assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) - val res45 = tensor4.dot(tensor5) - assertTrue(res45.mutableBuffer.array() contentEquals doubleArrayOf( - 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, - 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 - )) + val res45 = tensor4.matmul(tensor5) + assertTrue( + res45.source contentEquals doubleArrayOf( + 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, + 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 + ) + ) assertTrue(res45.shape contentEquals intArrayOf(2, 3, 3)) } @@ -140,31 +144,44 @@ internal class TestDoubleTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) - assertTrue(diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 5, 5)) - assertTrue(diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 6, 6)) - assertTrue(diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals - intArrayOf(7, 2, 3, 7, 4)) + assertTrue( + diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 5, 5) + ) + assertTrue( + diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 6, 6) + ) + assertTrue( + diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals + intArrayOf(7, 2, 3, 7, 4) + ) val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3)) - assertTrue(diagonal1.mutableBuffer.array() contentEquals - doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) + assertTrue( + diagonal1.source contentEquals + doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0) + ) val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0) assertTrue(diagonal1Offset.shape contentEquals intArrayOf(4, 4)) - assertTrue(diagonal1Offset.mutableBuffer.array() contentEquals - doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) + assertTrue( + diagonal1Offset.source contentEquals + doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0) + ) val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) assertTrue(diagonal2.shape contentEquals intArrayOf(4, 2, 4)) - assertTrue(diagonal2.mutableBuffer.array() contentEquals - doubleArrayOf( - 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, - 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + assertTrue( + diagonal2.source contentEquals + doubleArrayOf( + 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, + 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + ) + ) } @Test @@ -178,4 +195,14 @@ internal class TestDoubleTensorAlgebra { assertFalse(tensor1.eq(tensor3)) } + + @Test + fun testMap() = DoubleTensorAlgebra { + val tensor = one(5, 5, 5) + val l = tensor.getTensor(0).map { it + 1.0 } + val r = tensor.getTensor(1).map { it - 1.0 } + val res = l + r + assertTrue { intArrayOf(5, 5) contentEquals res.shape } + assertEquals(2.0, res[4, 4]) + } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt new file mode 100644 index 000000000..e9fc7fb9c --- /dev/null +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2018-2022 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.tensors.core + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.indices +import kotlin.jvm.JvmName + + +/** + * Simplified [DoubleBuffer] to array comparison + */ +public fun OffsetDoubleBuffer.contentEquals(vararg doubles: Double): Boolean = indices.all { get(it) == doubles[it] } + +@JvmName("contentEqualsArray") +public infix fun OffsetDoubleBuffer.contentEquals(otherArray: DoubleArray): Boolean = contentEquals(*otherArray) + +@JvmName("contentEqualsBuffer") +public infix fun OffsetDoubleBuffer.contentEquals(otherBuffer: Buffer): Boolean = + indices.all { get(it) == otherBuffer[it] } \ No newline at end of file diff --git a/kmath-trajectory/README.md b/kmath-trajectory/README.md new file mode 100644 index 000000000..ac2930b04 --- /dev/null +++ b/kmath-trajectory/README.md @@ -0,0 +1,34 @@ +# kmath-trajectory + + + + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-trajectory:0.3.1-dev-1`. + +**Gradle Groovy:** +```groovy +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-trajectory:0.3.1-dev-1' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:kmath-trajectory:0.3.1-dev-1") +} +``` + +## Contributors +Erik Schouten (github: @ESchouten, email: erik-schouten@hotmail.nl) diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts new file mode 100644 index 000000000..16a84b691 --- /dev/null +++ b/kmath-trajectory/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("space.kscience.gradle.mpp") +} + +kscience{ + native() + withContextReceivers() + dependencies { + api(projects.kmath.kmathGeometry) + } +} + +readme { + description = "Path and trajectory optimization" + maturity = space.kscience.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) +} diff --git a/kmath-trajectory/docs/README-TEMPLATE.md b/kmath-trajectory/docs/README-TEMPLATE.md new file mode 100644 index 000000000..eb8e4a0c0 --- /dev/null +++ b/kmath-trajectory/docs/README-TEMPLATE.md @@ -0,0 +1,13 @@ +# kmath-trajectory + + +${features} + +${artifact} + +## Author +Erik Schouten + +Github: ESchouten + +Email: erik-schouten@hotmail.nl diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt new file mode 100644 index 000000000..e90e3de41 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -0,0 +1,193 @@ +/* + * Copyright 2018-2022 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.trajectory + +import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import kotlin.math.PI +import kotlin.math.acos +import kotlin.math.cos +import kotlin.math.sin + +internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first + +internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second + +internal fun Pose2D.getTangentCircles(radius: Double): Pair = with(Euclidean2DSpace) { + val dX = radius * cos(theta) + val dY = radius * sin(theta) + return Circle2D(vector(x - dX, y + dY), radius) to Circle2D(vector(x + dX, y - dY), radius) +} + +internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, ArcSegment.Direction.LEFT) + +internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, + ArcSegment.Direction.RIGHT +) + +private fun outerTangent(a: Circle2D, b: Circle2D, side: ArcSegment.Direction): StraightSegment = with(Euclidean2DSpace){ + val centers = StraightSegment(a.center, b.center) + val p1 = when (side) { + ArcSegment.Direction.LEFT -> vector( + a.center.x - a.radius * cos(centers.theta), + a.center.y + a.radius * sin(centers.theta) + ) + ArcSegment.Direction.RIGHT -> vector( + a.center.x + a.radius * cos(centers.theta), + a.center.y - a.radius * sin(centers.theta) + ) + } + return StraightSegment( + p1, + vector(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) + ) +} + +internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, ArcSegment.Direction.LEFT) + +internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, ArcSegment.Direction.RIGHT) + +private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.Direction): StraightSegment? = with(Euclidean2DSpace){ + val centers = StraightSegment(base.center, direction.center) + if (centers.length < base.radius * 2) return null + val angle = theta( + when (side) { + ArcSegment.Direction.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + ArcSegment.Direction.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + } + ) + val dX = base.radius * sin(angle) + val dY = base.radius * cos(angle) + val p1 = vector(base.center.x + dX, base.center.y + dY) + val p2 = vector(direction.center.x - dX, direction.center.y - dY) + return StraightSegment(p1, p2) +} + +internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) + +public class DubinsPath( + public val a: ArcSegment, + public val b: Trajectory, + public val c: ArcSegment, +) : CompositeTrajectory(listOf(a,b,c)) { + + public val type: TYPE = TYPE.valueOf( + arrayOf( + a.direction.name[0], + if (b is ArcSegment) b.direction.name[0] else 'S', + c.direction.name[0] + ).toCharArray().concatToString() + ) + + public enum class TYPE { + RLR, LRL, RSR, LSL, RSL, LSR + } + + public companion object { + public fun all( + start: Pose2D, + end: Pose2D, + turningRadius: Double, + ): List = listOfNotNull( + rlr(start, end, turningRadius), + lrl(start, end, turningRadius), + rsr(start, end, turningRadius), + lsl(start, end, turningRadius), + rsl(start, end, turningRadius), + lsr(start, end, turningRadius) + ) + + public fun shortest(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath = + all(start, end, turningRadius).minBy { it.length } + + public fun rlr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace){ + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val centers = StraightSegment(c1.center, c2.center) + if (centers.length > turningRadius * 4) return null + + var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = vector(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle2D(p, turningRadius) + val p1 = vector(c1.center.x + dX, c1.center.y + dY) + theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = vector(e.center.x + dX, e.center.y + dY) + val a1 = ArcSegment.of(c1.center, start, p1, ArcSegment.Direction.RIGHT) + val a2 = ArcSegment.of(e.center, p1, p2, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, p2, end, ArcSegment.Direction.RIGHT) + return DubinsPath(a1, a2, a3) + } + + public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath?= with(Euclidean2DSpace) { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val centers = StraightSegment(c1.center, c2.center) + if (centers.length > turningRadius * 4) return null + + var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = vector(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle2D(p, turningRadius) + val p1 = vector(c1.center.x + dX, c1.center.y + dY) + theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = vector(e.center.x + dX, e.center.y + dY) + val a1 = ArcSegment.of(c1.center, start, p1, ArcSegment.Direction.LEFT) + val a2 = ArcSegment.of(e.center, p1, p2, ArcSegment.Direction.RIGHT) + val a3 = ArcSegment.of(c2.center, p2, end, ArcSegment.Direction.LEFT) + return DubinsPath(a1, a2, a3) + } + + public fun rsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftOuterTangent(c1, c2) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.RIGHT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.RIGHT) + return DubinsPath(a1, s, a3) + } + + public fun lsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightOuterTangent(c1, c2) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.LEFT) + return DubinsPath(a1, s, a3) + } + + public fun rsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightInnerTangent(c1, c2) + if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null + + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.RIGHT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.LEFT) + return DubinsPath(a1, s, a3) + } + + public fun lsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftInnerTangent(c1, c2) + if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null + + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.RIGHT) + return DubinsPath(a1, s, a3) + } + } +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt new file mode 100644 index 000000000..788cf57af --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2018-2022 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.trajectory + +import space.kscience.kmath.geometry.DoubleVector2D +import space.kscience.kmath.geometry.Vector +import kotlin.math.atan2 + +/** + * Combination of [Vector] and its view angle + */ +public interface Pose2D: DoubleVector2D{ + public val coordinate: DoubleVector2D + public val theta: Double +} + +public class PhaseVector2D( + override val coordinate: DoubleVector2D, + public val velocity: DoubleVector2D +): Pose2D, DoubleVector2D by coordinate{ + override val theta: Double get() = atan2(velocity.y, velocity.x) +} + +internal class Pose2DImpl( + override val coordinate: DoubleVector2D, + override val theta: Double +) : Pose2D, DoubleVector2D by coordinate + + +public fun Pose2D(coordinate: DoubleVector2D, theta: Double): Pose2D = Pose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt new file mode 100644 index 000000000..03b0fcec9 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2018-2022 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.trajectory + +import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.DoubleVector2D +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.circumference +import kotlin.math.PI +import kotlin.math.atan2 + +public sealed interface Trajectory { + public val length: Double +} + +/** + * Straight path segment. The order of start and end defines the direction + */ +public data class StraightSegment( + internal val start: DoubleVector2D, + internal val end: DoubleVector2D, +) : Trajectory { + override val length: Double get() = start.distanceTo(end) + + internal val theta: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) +} + +/** + * An arc segment + */ +public data class ArcSegment( + public val circle: Circle2D, + public val start: Pose2D, + public val end: Pose2D, +) : Trajectory { + + public enum class Direction { + LEFT, RIGHT + } + + override val length: Double by lazy { + val angle: Double = theta( + if (direction == Direction.LEFT) { + start.theta - end.theta + } else { + end.theta - start.theta + } + ) + val proportion = angle / (2 * PI) + circle.circumference * proportion + } + + internal val direction: Direction by lazy { + if (start.y < circle.center.y) { + if (start.theta > PI) Direction.RIGHT else Direction.LEFT + } else if (start.y > circle.center.y) { + if (start.theta < PI) Direction.RIGHT else Direction.LEFT + } else { + if (start.theta == 0.0) { + if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT + } else { + if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + } + } + } + + public companion object { + public fun of(center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, direction: Direction): ArcSegment { + fun calculatePose( + vector: DoubleVector2D, + theta: Double, + direction: Direction, + ): Pose2D = Pose2D( + vector, + when (direction) { + Direction.LEFT -> theta(theta - PI / 2) + Direction.RIGHT -> theta(theta + PI / 2) + } + ) + + val s1 = StraightSegment(center, start) + val s2 = StraightSegment(center, end) + val pose1 = calculatePose(start, s1.theta, direction) + val pose2 = calculatePose(end, s2.theta, direction) + return ArcSegment(Circle2D(center, s1.length), pose1, pose2) + } + } +} + +public open class CompositeTrajectory(public val segments: Collection) : Trajectory { + override val length: Double get() = segments.sumOf { it.length } +} + diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt new file mode 100644 index 000000000..3782a9a32 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2022 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.trajectory + +public fun interface TrajectoryCost { + public fun estimate(trajectory: Trajectory): Double + + public companion object{ + public val length: TrajectoryCost = TrajectoryCost { it.length } + } +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt new file mode 100644 index 000000000..2e8e43be9 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2022 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.trajectory + +public fun interface MaxCurvature { + public fun compute(startPoint: PhaseVector2D): Double +} + +public fun DubinsPath.Companion.shortest( + start: PhaseVector2D, + end: PhaseVector2D, + computer: MaxCurvature, +): DubinsPath = shortest(start, end, computer.compute(start)) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt new file mode 100644 index 000000000..3b2535cee --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2022 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.trajectory + +import space.kscience.kmath.geometry.Euclidean2DSpace +import kotlin.math.PI +import kotlin.math.abs +import kotlin.math.sin + +const val maxFloatDelta = 0.000001 + +fun Double.radiansToDegrees() = this * 180 / PI + +fun Double.equalFloat(other: Double) = abs(this - other) < maxFloatDelta +fun Pose2D.equalsFloat(other: Pose2D) = x.equalFloat(other.x) && y.equalFloat(other.y) && theta.equalFloat(other.theta) + +fun StraightSegment.inverse() = StraightSegment(end, start) +fun StraightSegment.shift(shift: Int, width: Double): StraightSegment = with(Euclidean2DSpace){ + val dX = width * sin(inverse().theta) + val dY = width * sin(theta) + + return StraightSegment( + vector(start.x - dX * shift, start.y - dY * shift), + vector(end.x - dX * shift, end.y - dY * shift) + ) +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt new file mode 100644 index 000000000..166567475 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2018-2022 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.trajectory.dubins + +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.trajectory.* +import kotlin.test.Test +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + + +class DubinsTests { + + @Test + fun dubinsTest() = with(Euclidean2DSpace){ + val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) + val lineP1 = straight.shift(1, 10.0).inverse() + + val start = Pose2D(straight.end, straight.theta) + val end = Pose2D(lineP1.start, lineP1.theta) + val radius = 2.0 + val dubins = DubinsPath.all(start, end, radius) + + val absoluteDistance = start.distanceTo(end) + println("Absolute distance: $absoluteDistance") + + val expectedLengths = mapOf( + DubinsPath.TYPE.RLR to 13.067681939031397, + DubinsPath.TYPE.RSR to 12.28318530717957, + DubinsPath.TYPE.LSL to 32.84955592153878, + DubinsPath.TYPE.RSL to 23.37758938854081, + DubinsPath.TYPE.LSR to 23.37758938854081 + ) + + expectedLengths.forEach { + val path = dubins.find { p -> p.type === it.key } + assertNotNull(path, "Path ${it.key} not found") + println("${it.key}: ${path.length}") + assertTrue(it.value.equalFloat(path.length)) + + assertTrue(start.equalsFloat(path.a.start)) + assertTrue(end.equalsFloat(path.c.end)) + + // Not working, theta double precision inaccuracy + if (path.b is ArcSegment) { + val b = path.b as ArcSegment + assertTrue(path.a.end.equalsFloat(b.start)) + assertTrue(path.c.start.equalsFloat(b.end)) + } else if (path.b is StraightSegment) { + val b = path.b as StraightSegment + assertTrue(path.a.end.equalsFloat(Pose2D(b.start, b.theta))) + assertTrue(path.c.start.equalsFloat(Pose2D(b.end, b.theta))) + } + } + } +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt new file mode 100644 index 000000000..86c79a5d6 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2018-2022 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.trajectory.segments + +import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.circumference +import space.kscience.kmath.trajectory.ArcSegment +import space.kscience.kmath.trajectory.radiansToDegrees +import kotlin.test.Test +import kotlin.test.assertEquals + +class ArcTests { + + @Test + fun arcTest() = with(Euclidean2DSpace){ + val circle = Circle2D(vector(0.0, 0.0), 2.0) + val arc = ArcSegment.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), ArcSegment.Direction.RIGHT) + assertEquals(circle.circumference / 4, arc.length, 1.0) + assertEquals(0.0, arc.start.theta.radiansToDegrees()) + assertEquals(90.0, arc.end.theta.radiansToDegrees()) + } +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt new file mode 100644 index 000000000..5321fb1a1 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2018-2022 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.trajectory.segments + +import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.circumference +import space.kscience.kmath.trajectory.maxFloatDelta +import kotlin.test.Test +import kotlin.test.assertEquals + +class CircleTests { + + @Test + fun arcTest() { + val center = Euclidean2DSpace.vector(0.0, 0.0) + val radius = 2.0 + val expectedCircumference = 12.56637 + val circle = Circle2D(center, radius) + assertEquals(expectedCircumference, circle.circumference, maxFloatDelta) + } +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt new file mode 100644 index 000000000..c5e88c1f1 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2018-2022 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.trajectory.segments + +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.trajectory.StraightSegment +import space.kscience.kmath.trajectory.radiansToDegrees +import kotlin.math.pow +import kotlin.math.sqrt +import kotlin.test.Test +import kotlin.test.assertEquals + +class LineTests { + + @Test + fun lineTest() = with(Euclidean2DSpace){ + val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) + assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), straight.length) + assertEquals(45.0, straight.theta.radiansToDegrees()) + } + + @Test + fun lineAngleTest() = with(Euclidean2DSpace){ + //val zero = Vector2D(0.0, 0.0) + val north = StraightSegment(Euclidean2DSpace.zero, vector(0.0, 2.0)) + assertEquals(0.0, north.theta.radiansToDegrees()) + val east = StraightSegment(Euclidean2DSpace.zero, vector(2.0, 0.0)) + assertEquals(90.0, east.theta.radiansToDegrees()) + val south = StraightSegment(Euclidean2DSpace.zero, vector(0.0, -2.0)) + assertEquals(180.0, south.theta.radiansToDegrees()) + val west = StraightSegment(Euclidean2DSpace.zero, vector(-2.0, 0.0)) + assertEquals(270.0, west.theta.radiansToDegrees()) + } +} diff --git a/kmath-viktor/README.md b/kmath-viktor/README.md index 5d7c2dea1..abff20427 100644 --- a/kmath-viktor/README.md +++ b/kmath-viktor/README.md @@ -6,7 +6,7 @@ Binding for https://github.com/JetBrains-Research/viktor ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-viktor:0.3.0' + implementation 'space.kscience:kmath-viktor:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-viktor:0.3.0") + implementation("space.kscience:kmath-viktor:0.3.1-dev-1") } ``` diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 2e932b441..7a135f316 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,15 +1,14 @@ plugins { - kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.jvm") } description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) - api("org.jetbrains.bio:viktor:1.1.0") + api("org.jetbrains.bio:viktor:1.2.0") } readme { - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt index 4eedcb5ee..52dc1e192 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -13,7 +13,7 @@ import space.kscience.kmath.structures.MutableBuffer @JvmInline public value class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { override val size: Int - get() = flatArray.size + get() = flatArray.length override inline fun get(index: Int): Double = flatArray[index] diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt index 1d4d6cebd..493af54c9 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -117,6 +117,7 @@ public open class ViktorFieldOpsND : public val DoubleField.viktorAlgebra: ViktorFieldOpsND get() = ViktorFieldOpsND +@OptIn(UnstableKMathAPI::class) public open class ViktorFieldND( override val shape: Shape, ) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 25ca3a10e..c9749d41a 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/settings.gradle.kts b/settings.gradle.kts index b3c275810..f53232f44 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,12 +1,32 @@ rootProject.name = "kmath" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +dependencyResolutionManagement { + val toolsVersion: String by extra + + repositories { + mavenLocal() + maven("https://repo.kotlin.link") + mavenCentral() + gradlePluginPortal() + } + + versionCatalogs { + create("npmlibs") { + from("space.kscience:version-catalog:$toolsVersion") + } + } +} + include( + ":test-utils", ":kmath-memory", ":kmath-complex", ":kmath-core", ":kmath-coroutines", ":kmath-functions", + ":kmath-polynomial", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", @@ -25,6 +45,7 @@ include( ":kmath-jupyter", ":kmath-symja", ":kmath-jafama", + ":kmath-trajectory", ":examples", ":benchmarks", ) diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts new file mode 100644 index 000000000..98bd7328d --- /dev/null +++ b/test-utils/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("space.kscience.gradle.mpp") +} + +kscience{ + native() +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmath.kmathCore) + api(kotlin("test")) + } + } +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt b/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt similarity index 88% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt rename to test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt index ddd8fc3ea..261e74f5a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt +++ b/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt b/test-utils/src/commonMain/kotlin/FieldVerifier.kt similarity index 93% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt rename to test-utils/src/commonMain/kotlin/FieldVerifier.kt index 20a7b6a72..a03ca0a27 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt +++ b/test-utils/src/commonMain/kotlin/FieldVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal class FieldVerifier>( +public class FieldVerifier>( algebra: A, a: T, b: T, c: T, x: Number, ) : RingVerifier(algebra, a, b, c, x) { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt b/test-utils/src/commonMain/kotlin/RingVerifier.kt similarity index 93% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt rename to test-utils/src/commonMain/kotlin/RingVerifier.kt index daf18834a..c40075d93 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt +++ b/test-utils/src/commonMain/kotlin/RingVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals -internal open class RingVerifier(algebra: A, a: T, b: T, c: T, x: Number) : +public open class RingVerifier(algebra: A, a: T, b: T, c: T, x: Number) : SpaceVerifier(algebra, a, b, c, x) where A : Ring, A : ScaleOperations { override fun verify() { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt similarity index 90% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt rename to test-utils/src/commonMain/kotlin/SpaceVerifier.kt index 951197fc6..01c02997b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 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. */ @@ -11,12 +11,12 @@ import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal open class SpaceVerifier( +public open class SpaceVerifier( override val algebra: S, - val a: T, - val b: T, - val c: T, - val x: Number, + public val a: T, + public val b: T, + public val c: T, + public val x: Number, ) : AlgebraicVerifier> where S : Ring, S : ScaleOperations { override fun verify() { algebra { diff --git a/test-utils/src/commonMain/kotlin/asserts.kt b/test-utils/src/commonMain/kotlin/asserts.kt new file mode 100644 index 000000000..8ddce517c --- /dev/null +++ b/test-utils/src/commonMain/kotlin/asserts.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2022 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.testutils + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices +import kotlin.test.assertEquals +import kotlin.test.fail + +public fun assertBufferEquals(expected: Buffer, result: Buffer, tolerance: Double = 1e-4) { + if (expected.size != result.size) { + fail("Expected size is ${expected.size}, but the result size is ${result.size}") + } + expected.indices.forEach { + assertEquals(expected[it], result[it], tolerance) + } +} \ No newline at end of file diff --git a/test-utils/src/commonMain/kotlin/bufferEquality.kt b/test-utils/src/commonMain/kotlin/bufferEquality.kt new file mode 100644 index 000000000..9e4d9ec22 --- /dev/null +++ b/test-utils/src/commonMain/kotlin/bufferEquality.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2022 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.testutils + +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.jvm.JvmName + +/** + * Simplified [DoubleBuffer] to array comparison + */ +public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) + +@JvmName("contentEqualsArray") +public infix fun DoubleBuffer.contentEquals(otherArray: DoubleArray): Boolean = array.contentEquals(otherArray) + +@JvmName("contentEqualsBuffer") +public infix fun DoubleBuffer.contentEquals(otherBuffer: DoubleBuffer): Boolean = array.contentEquals(otherBuffer.array) \ No newline at end of file