From bf504ae6c5b9bc25655ee543426325ba40529ed8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 5 Nov 2021 16:58:13 +0300 Subject: [PATCH 01/72] Basic series --- build.gradle.kts | 3 +- .../space/kscience/kmath/series/analyzeDif.kt | 37 ++++ .../kmath/structures/StreamDoubleFieldND.kt | 2 +- kmath-core/build.gradle.kts | 7 - .../kmath/domains/HyperSquareDomain.kt | 1 - .../kmath/expressions/specialExpressions.kt | 1 - .../kmath/linear/BufferedLinearSpace.kt | 3 +- .../space/kscience/kmath/nd/AlgebraND.kt | 2 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 20 +-- .../space/kscience/kmath/nd/BufferND.kt | 16 +- .../space/kscience/kmath/nd/DoubleFieldND.kt | 8 +- .../nd/{ShapeIndexer.kt => ShapeIndices.kt} | 4 +- .../space/kscience/kmath/nd/StructureND.kt | 6 +- .../kmath/operations/bufferOperation.kt | 11 +- .../space/kscience/kmath/structures/Buffer.kt | 11 +- .../space/kscience/kmath/real/RealVector.kt | 1 - .../space/kscience/kmath/real/realND.kt | 4 +- .../kmath/integration/GaussIntegrator.kt | 1 - .../kscience/kmath/series/SeriesAlgebra.kt | 170 ++++++++++++++++++ .../kotlin/space/kscience/kmath/stat/Mean.kt | 5 +- .../core/BroadcastDoubleTensorAlgebra.kt | 16 +- .../kmath/tensors/core/BufferedTensor.kt | 10 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 11 +- .../tensors/core/internal/broadcastUtils.kt | 14 +- .../kmath/tensors/core/internal/linUtils.kt | 3 + .../tensors/core/internal/tensorCastsUtils.kt | 2 +- .../kmath/tensors/core/internal/utils.kt | 2 +- settings.gradle.kts | 4 +- 28 files changed, 291 insertions(+), 84 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{ShapeIndexer.kt => ShapeIndices.kt} (95%) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt diff --git a/build.gradle.kts b/build.gradle.kts index c2347f7be..7fb995aa1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ import java.net.URL plugins { id("ru.mipt.npm.gradle.project") + id("org.jetbrains.kotlinx.kover") version "0.4.1" kotlin("jupyter.api") apply false } @@ -69,4 +70,4 @@ ksciencePublish { sonatype(publish = true) } -apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") +apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt new file mode 100644 index 000000000..466aa2039 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -0,0 +1,37 @@ +package space.kscience.kmath.series + + +import net.jafama.StrictFastMath.abs +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.toList +import space.kscience.kmath.structures.Buffer +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.scatter +import kotlin.math.PI +import kotlin.math.max + +fun main() = Double.algebra.bufferAlgebra.seriesAlgebra(0..100).invoke { + fun Buffer.plot() { + val ls = labels + Plotly.plot { + scatter { + x.numbers = ls + y.numbers = toList() + } + }.makeFile() + } + + + val s1 = series(100) { sin(2 * PI * it / 100) } + val s2 = series(100) { 1.0 } + + (s1 - s2).plot() + + // Kolmogorov-Smirnov test statistic + val kst = (s1 - s2).fold(0.0) { sup, arg -> max(sup, abs(arg))} + + +} \ No newline at end of file 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 05a13f5d2..134c91e4a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -36,7 +36,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND this.buffer as DoubleBuffer + this is BufferND && this.shapeIndices == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index e4436c1df..564d06f49 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -2,7 +2,6 @@ plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.native") -// id("com.xcporter.metaview") version "0.0.5" } kotlin.sourceSets { @@ -13,12 +12,6 @@ kotlin.sourceSets { } } -//generateUml { -// classTree { -// -// } -//} - readme { description = "Core classes, algebra definitions, basic linear algebra" maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT 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 7ea3e22c4..2b288172a 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.domains import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.indices /** * 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..d68869491 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 @@ -8,7 +8,6 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.indices import kotlin.jvm.JvmName /** 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 410fb8505..7674012e6 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 @@ -13,11 +13,10 @@ 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 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 113bd4c52..9022b886a 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 @@ -26,7 +26,7 @@ public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(sha public interface WithShape { public val shape: Shape - public val indices: ShapeIndexer get() = DefaultStrides(shape) + public val shapeIndices: ShapeIndices get() = DefaultStrides(shape) } /** 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 d25b455f4..447062886 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 @@ -13,7 +13,7 @@ import space.kscience.kmath.operations.* import space.kscience.kmath.structures.BufferFactory public interface BufferAlgebraND> : AlgebraND { - public val indexerBuilder: (IntArray) -> ShapeIndexer + public val indexerBuilder: (IntArray) -> ShapeIndices public val bufferAlgebra: BufferAlgebra override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra @@ -47,7 +47,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) -> ShapeIndices = DefaultStrides.Companion::invoke } } @@ -55,7 +55,7 @@ public inline fun > BufferAlgebraND.mapInline( arg: BufferND, crossinline transform: A.(T) -> T, ): BufferND { - val indexes = arg.indices + val indexes = arg.shapeIndices val buffer = arg.buffer return BufferND( indexes, @@ -69,7 +69,7 @@ internal inline fun > BufferAlgebraND.mapIndexedInline( arg: BufferND, crossinline transform: A.(index: IntArray, arg: T) -> T, ): BufferND { - val indexes = arg.indices + val indexes = arg.shapeIndices val buffer = arg.buffer return BufferND( indexes, @@ -84,8 +84,8 @@ internal inline fun > BufferAlgebraND.zipInline( r: BufferND, crossinline block: A.(l: T, r: T) -> T, ): BufferND { - require(l.indices == r.indices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } - val indexes = l.indices + require(l.shapeIndices == r.shapeIndices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } + val indexes = l.shapeIndices val lbuffer = l.buffer val rbuffer = r.buffer return BufferND( @@ -99,25 +99,25 @@ internal inline fun > BufferAlgebraND.zipInline( @OptIn(PerformancePitfall::class) public open class BufferedGroupNDOps>( override val bufferAlgebra: BufferAlgebra, - override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + override val indexerBuilder: (IntArray) -> ShapeIndices = BufferAlgebraND.defaultIndexerBuilder, ) : GroupOpsND, BufferAlgebraND { override fun StructureND.unaryMinus(): StructureND = map { -it } } public open class BufferedRingOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (IntArray) -> ShapeIndices = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedGroupNDOps(bufferAlgebra, indexerBuilder), RingOpsND public open class BufferedFieldOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (IntArray) -> ShapeIndices = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedRingOpsND(bufferAlgebra, indexerBuilder), FieldOpsND { public constructor( elementAlgebra: A, bufferFactory: BufferFactory, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (IntArray) -> ShapeIndices = BufferAlgebraND.defaultIndexerBuilder, ) : this(BufferFieldOps(elementAlgebra, bufferFactory), indexerBuilder) @OptIn(PerformancePitfall::class) 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 515988159..eea382492 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 @@ -14,17 +14,17 @@ import space.kscience.kmath.structures.MutableBufferFactory * Represents [StructureND] over [Buffer]. * * @param T the type of items. - * @param indices The strides to access elements of [Buffer] by linear indices. + * @param shapeIndices The strides to access elements of [Buffer] by linear indices. * @param buffer The underlying buffer. */ public open class BufferND( - override val indices: ShapeIndexer, + override val shapeIndices: ShapeIndices, public open val buffer: Buffer, ) : StructureND { - override operator fun get(index: IntArray): T = buffer[indices.offset(index)] + override operator fun get(index: IntArray): T = buffer[shapeIndices.offset(index)] - override val shape: IntArray get() = indices.shape + override val shape: IntArray get() = shapeIndices.shape override fun toString(): String = StructureND.toString(this) } @@ -37,7 +37,7 @@ public inline fun StructureND.mapToBuffer( crossinline transform: (T) -> R, ): BufferND { return if (this is BufferND) - BufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) + BufferND(this.shapeIndices, factory.invoke(shapeIndices.linearSize) { transform(buffer[it]) }) else { val strides = DefaultStrides(shape) BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) @@ -52,11 +52,11 @@ public inline fun StructureND.mapToBuffer( * @param buffer The underlying buffer. */ public class MutableBufferND( - strides: ShapeIndexer, + strides: ShapeIndices, override val buffer: MutableBuffer, ) : MutableStructureND, BufferND(strides, buffer) { override fun set(index: IntArray, value: T) { - buffer[indices.offset(index)] = value + buffer[shapeIndices.offset(index)] = value } } @@ -68,7 +68,7 @@ public inline fun MutableStructureND.mapToMutableBuffer( crossinline transform: (T) -> R, ): MutableBufferND { return if (this is MutableBufferND) - MutableBufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) + MutableBufferND(this.shapeIndices, factory.invoke(shapeIndices.linearSize) { transform(buffer[it]) }) else { val strides = DefaultStrides(shape) MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) 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 8baeac21f..c51f80346 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 @@ -14,7 +14,7 @@ import kotlin.contracts.contract import kotlin.math.pow as kpow public class DoubleBufferND( - indexes: ShapeIndexer, + indexes: ShapeIndices, override val buffer: DoubleBuffer, ) : BufferND(indexes, buffer) @@ -34,7 +34,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D arg: DoubleBufferND, transform: (Double) -> Double, ): DoubleBufferND { - val indexes = arg.indices + val indexes = arg.shapeIndices val array = arg.buffer.array return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { transform(array[it]) }) } @@ -44,8 +44,8 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D r: DoubleBufferND, block: (l: Double, r: Double) -> Double, ): DoubleBufferND { - require(l.indices == r.indices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } - val indexes = l.indices + require(l.shapeIndices == r.shapeIndices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } + val indexes = l.shapeIndices val lArray = l.buffer.array val rArray = r.buffer.array return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { block(lArray[it], rArray[it]) }) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index 20e180dd1..151899999 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -10,7 +10,7 @@ import kotlin.native.concurrent.ThreadLocal /** * A converter from linear index to multivariate index */ -public interface ShapeIndexer: Iterable{ +public interface ShapeIndices: 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: ShapeIndices { /** * Array strides */ 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 614d97950..9256f0ba2 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 @@ -54,7 +54,7 @@ public interface StructureND : Featured, WithShape { * @return the lazy sequence of pairs of indices to values. */ @PerformancePitfall - public fun elements(): Sequence> = indices.asSequence().map { it to get(it) } + public fun elements(): Sequence> = shapeIndices.asSequence().map { it to get(it) } /** * Feature is some additional structure information that allows to access it special properties or hints. @@ -71,7 +71,7 @@ public interface StructureND : Featured, WithShape { if (st1 === st2) return true // fast comparison of buffers if possible - if (st1 is BufferND && st2 is BufferND && st1.indices == st2.indices) + if (st1 is BufferND && st2 is BufferND && st1.shapeIndices == st2.shapeIndices) return Buffer.contentEquals(st1.buffer, st2.buffer) //element by element comparison if it could not be avoided @@ -87,7 +87,7 @@ public interface StructureND : Featured, WithShape { if (st1 === st2) return true // fast comparison of buffers if possible - if (st1 is BufferND && st2 is BufferND && st1.indices == st2.indices) + if (st1 is BufferND && st2 is BufferND && st1.shapeIndices == st2.shapeIndices) return Buffer.contentEquals(st1.buffer, st2.buffer) //element by element comparison if it could not be avoided 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 6bf3266e3..115f8c23a 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 @@ -61,14 +61,14 @@ 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)) } @@ -77,15 +77,16 @@ public inline fun Buffer.map( * 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( +public inline fun Buffer.mapIndexed( bufferFactory: BufferFactory = Buffer.Companion::auto, crossinline block: (index: Int, value: T) -> R, ): Buffer = bufferFactory(size) { block(it, get(it)) } /** * Fold given buffer according to [operation] + * TODO add element algebra as fold receiver */ -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 @@ -95,7 +96,7 @@ public inline fun Buffer.fold(initial: R, operation: (acc: R, T) * Zip two buffers using given [transform]. */ @UnstableKMathAPI -public inline fun Buffer.zip( +public inline fun Buffer.zip( other: Buffer, bufferFactory: BufferFactory = Buffer.Companion::auto, crossinline transform: (T1, T2) -> R, 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 c68bca2d9..2c34327b5 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 @@ -48,6 +48,11 @@ public interface Buffer { override fun toString(): String + /** + * Returns an [IntRange] of the valid indices for this [Buffer]. + */ + public val indices: IntRange get() = 0 until size + public companion object { public fun toString(buffer: Buffer<*>): String = @@ -100,10 +105,12 @@ public interface Buffer { } } +public operator fun Buffer.get(index: UInt): T = get(index.toInt()) + /** - * Returns an [IntRange] of the valid indices for this [Buffer]. + * if index is in range of buffer, return the value. Otherwise, return null. */ -public val Buffer<*>.indices: IntRange get() = 0 until size +public fun Buffer.getOrNull(index: Int): T? = if (index in indices) get(index) else null /** * Immutable wrapper for [MutableBuffer]. diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index cca1c3551..b108f696e 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -11,7 +11,6 @@ import space.kscience.kmath.operations.DoubleL2Norm import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer.Companion.double import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.structures.indices import kotlin.math.pow public typealias DoubleVector = Point 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 56f50acbc..dc8f259bc 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 @@ -13,8 +13,8 @@ import space.kscience.kmath.structures.DoubleBuffer * Map one [BufferND] using function without indices. */ public inline fun BufferND.mapInline(crossinline transform: DoubleField.(Double) -> Double): BufferND { - val array = DoubleArray(indices.linearSize) { offset -> DoubleField.transform(buffer[offset]) } - return BufferND(indices, DoubleBuffer(array)) + val array = DoubleArray(shapeIndices.linearSize) { offset -> DoubleField.transform(buffer[offset]) } + return BufferND(shapeIndices, DoubleBuffer(array)) } /** 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 2b426d204..9ee292998 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 @@ -8,7 +8,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.structures.indices /** * A simple one-pass integrator based on Gauss rule diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt new file mode 100644 index 000000000..3bf8c66b3 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -0,0 +1,170 @@ +package space.kscience.kmath.series + +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.getOrNull +import kotlin.math.max +import kotlin.math.min + +private fun IntRange.intersect(other: IntRange): IntRange = + max(first, other.first)..min(last, other.last) + +private val IntRange.size get() = last - first + 1 + +private class BufferView(val buffer: Buffer, val offset: Int, override val size: Int) : Buffer { + init { + require(offset >= 0) { " Range offset must be positive" } + require(offset < buffer.size) { "Range offset is beyond the buffer size" } + require(size > 0) { "Size must be positive" } + require(size < buffer.size) { "Slice size is larger than the buffer" } + } + + override fun get(index: Int): T = buffer[index - offset] + + override fun iterator(): Iterator = buffer.asSequence().drop(offset).take(size).iterator() + + override fun toString(): String = "$buffer[${offset}:${offset + size - 1}]" + + override val indices: IntRange = offset until offset + size +} + +/** + * A scope to operation on series + */ +public class SeriesAlgebra, L>( + public val bufferAlgebra: BufferRingOps, + private val labelResolver: (Int) -> L, +) : RingOps> { + + public val elementAlgebra: A get() = bufferAlgebra.elementAlgebra + public val bufferFactory: BufferFactory get() = bufferAlgebra.bufferFactory + + public val Buffer.offset: UInt get() = indices.first.toUInt() + + /** + * Build a new series + */ + public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Buffer { + return bufferFactory(size) { + val index = it + fromIndex + elementAlgebra.block(labelResolver(index)) + }.moveTo(fromIndex) + } + + /** + * Move a series starting to start at a given index + */ + public fun Buffer.moveTo(index: Int): Buffer = if (index == 0) { + this + } else if (this is BufferView) { + BufferView(buffer, index.toInt(), size) + } else { + BufferView(this, index.toInt(), size) + } + + /** + * Create a buffer view using given range + */ + public fun Buffer.get(range: IntRange): Buffer { + val size = range.size + return if (this is BufferView) { + BufferView(this, indices.first + range.first, size) + } else { + BufferView(this, range.first, size) + } + } + + /** + * Get a label buffer for given buffer. + */ + public val Buffer.labels: List get() = indices.map(labelResolver) + + + /** + * Try to resolve element by label and return null if element with a given label is not found + */ + public operator fun Buffer.get(label: L): T? { + val index = labels.indexOf(label) + if (index == -1) return null + return get(index + offset.toInt()) + } + + override fun add(left: Buffer, right: Buffer): Buffer = elementAlgebra.invoke { + val newRange = left.indices.intersect(right.indices) + //TODO optimize copy at BufferAlgebra level + bufferFactory(newRange.size) { + val offset = it + newRange.first + left[offset] + right[offset] + }.moveTo(newRange.first) + } + + override fun Buffer.unaryMinus(): Buffer = map { -it } + + override fun multiply(left: Buffer, right: Buffer): Buffer = elementAlgebra.invoke { + val newRange = left.indices.intersect(right.indices) + bufferFactory(newRange.size) { + val offset = it + newRange.first + left[offset] * right[offset] + } + } + + /** + * Map a series to another series of the same size + */ + public inline fun Buffer.map(crossinline transform: A.(T) -> T): Buffer { + val buf = bufferFactory(size) { + elementAlgebra.transform(get(it)) + } + return buf.moveTo(indices.first) + } + + /** + * Map series to another series of the same size with label + */ + public inline fun Buffer.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Buffer { + val labels = labels + val buf = bufferFactory(size) { + elementAlgebra.transform(get(it), labels[it]) + } + return buf.moveTo(indices.first) + } + + public inline fun Buffer.fold(initial: R, operation: A.(acc: R, T) -> R): R { + var accumulator = initial + for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, get(index)) + return accumulator + } + + public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { + val labels = labels + var accumulator = initial + for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, get(index), labels[index]) + return accumulator + } + + /** + * Zip two buffers replacing missing values with [defaultValue] + */ + public inline fun Buffer.zip( + other: Buffer, + defaultValue: T, + crossinline operation: A.(left: T?, right: T?) -> T?, + ): Buffer { + val start = min(indices.first, other.indices.first) + val size = max(indices.last, other.indices.last) - start + return bufferFactory(size) { + elementAlgebra.operation( + getOrNull(it) ?: defaultValue, + other.getOrNull(it) ?: defaultValue + ) ?: defaultValue + } + } +} + +public fun , L> BufferRingOps.seriesAlgebra(labels: Iterable): SeriesAlgebra { + val l = labels.toList() + return SeriesAlgebra(this) { + if (it in l.indices) l[it] else error("Index $it is outside of labels range ${l.indices}") + } +} \ No newline at end of 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 2a9bd3cd4..70da58171 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.stat import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.indices /** * Arithmetic mean @@ -45,8 +44,10 @@ public class Mean( public companion object { @Deprecated("Use Double.mean instead") public val double: Mean = Mean(DoubleField) { sum, count -> sum / count } + @Deprecated("Use Int.mean instead") public val int: Mean = Mean(IntRing) { sum, count -> sum / count } + @Deprecated("Use Long.mean instead") public val long: Mean = Mean(LongRing) { sum, count -> sum / count } @@ -60,6 +61,6 @@ public class Mean( //TODO replace with optimized version which respects overflow public val Double.Companion.mean: Mean get() = Mean(DoubleField) { sum, count -> sum / count } public val Int.Companion.mean: Mean get() = Mean(IntRing) { sum, count -> sum / count } -public val Long.Companion.mean: Mean get() = Mean(LongRing) { sum, count -> sum / count } +public val Long.Companion.mean: Mean get() = Mean(LongRing) { sum, count -> sum / count } 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 10c747777..37c25e99f 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 @@ -26,7 +26,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, arg.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> + val resBuffer = DoubleArray(newThis.shapeIndices.linearSize) { i -> newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -34,7 +34,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.plusAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { + for (i in 0 until tensor.shapeIndices.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -44,7 +44,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, arg.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> + val resBuffer = DoubleArray(newThis.shapeIndices.linearSize) { i -> newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -52,7 +52,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.minusAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { + for (i in 0 until tensor.shapeIndices.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -62,7 +62,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, arg.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> + val resBuffer = DoubleArray(newThis.shapeIndices.linearSize) { i -> newThis.mutableBuffer.array()[newThis.bufferStart + i] * newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -71,7 +71,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.timesAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { + for (i in 0 until tensor.shapeIndices.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -81,7 +81,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, arg.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> + val resBuffer = DoubleArray(newThis.shapeIndices.linearSize) { i -> newThis.mutableBuffer.array()[newOther.bufferStart + i] / newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -90,7 +90,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.divAssign(arg: StructureND) { val newOther = broadcastTo(arg.tensor, tensor.shape) - for (i in 0 until tensor.indices.linearSize) { + for (i in 0 until tensor.shapeIndices.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= newOther.mutableBuffer.array()[tensor.bufferStart + i] } 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 54d8f54dc..0b1006b6c 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 @@ -22,22 +22,22 @@ public open class BufferedTensor internal constructor( /** * Buffer strides based on [TensorLinearStructure] implementation */ - override val indices: Strides get() = TensorLinearStructure(shape) + override val shapeIndices: Strides get() = TensorLinearStructure(shape) /** * Number of elements in tensor */ public val numElements: Int - get() = indices.linearSize + get() = shapeIndices.linearSize - override fun get(index: IntArray): T = mutableBuffer[bufferStart + indices.offset(index)] + override fun get(index: IntArray): T = mutableBuffer[bufferStart + shapeIndices.offset(index)] override fun set(index: IntArray, value: T) { - mutableBuffer[bufferStart + indices.offset(index)] = value + mutableBuffer[bufferStart + shapeIndices.offset(index)] = value } @PerformancePitfall - override fun elements(): Sequence> = indices.asSequence().map { + override fun elements(): Sequence> = shapeIndices.asSequence().map { it to get(it) } } 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 864900adb..6c6264989 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 @@ -15,7 +15,6 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.indices import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.Tensor @@ -63,7 +62,7 @@ public open class DoubleTensorAlgebra : val tensor = this.tensor //TODO remove additional copy val sourceArray = tensor.copyArray() - val array = DoubleArray(tensor.numElements) { DoubleField.transform(tensor.indices.index(it), sourceArray[it]) } + val array = DoubleArray(tensor.numElements) { DoubleField.transform(tensor.shapeIndices.index(it), sourceArray[it]) } return DoubleTensor( tensor.shape, array, @@ -365,11 +364,11 @@ public open class DoubleTensorAlgebra : val resTensor = DoubleTensor(resShape, resBuffer) for (offset in 0 until n) { - val oldMultiIndex = tensor.indices.index(offset) + val oldMultiIndex = tensor.shapeIndices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } - val linearIndex = resTensor.indices.offset(newMultiIndex) + val linearIndex = resTensor.shapeIndices.offset(newMultiIndex) resTensor.mutableBuffer.array()[linearIndex] = tensor.mutableBuffer.array()[tensor.bufferStart + offset] } @@ -467,7 +466,7 @@ public open class DoubleTensorAlgebra : val resTensor = zeros(resShape) for (i in 0 until diagonalEntries.tensor.numElements) { - val multiIndex = diagonalEntries.tensor.indices.index(i) + val multiIndex = diagonalEntries.tensor.shapeIndices.index(i) var offset1 = 0 var offset2 = abs(realOffset) @@ -592,7 +591,7 @@ public open class DoubleTensorAlgebra : val init = foldFunction(DoubleArray(1) { 0.0 }) val resTensor = BufferedTensor(resShape, MutableBuffer.auto(resNumElements) { init }, 0) - for (index in resTensor.indices) { + for (index in resTensor.shapeIndices) { val prefix = index.take(dim).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray() resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> 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 3787c0972..e0ea40b32 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 @@ -10,7 +10,7 @@ import kotlin.math.max internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { - val totalMultiIndex = resTensor.indices.index(linearIndex) + val totalMultiIndex = resTensor.shapeIndices.index(linearIndex) val curMultiIndex = tensor.shape.copyOf() val offset = totalMultiIndex.size - curMultiIndex.size @@ -23,7 +23,7 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } } - val curLinearIndex = tensor.indices.offset(curMultiIndex) + val curLinearIndex = tensor.shapeIndices.offset(curMultiIndex) resTensor.mutableBuffer.array()[linearIndex] = tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex] } @@ -112,7 +112,7 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List StructureND.copyToBufferedTensor(): BufferedTensor = internal fun StructureND.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this - is MutableBufferND -> if (this.indices == TensorLinearStructure(this.shape)) { + is MutableBufferND -> if (this.shapeIndices == TensorLinearStructure(this.shape)) { BufferedTensor(this.shape, this.buffer, 0) } else { this.copyToBufferedTensor() 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 553ed6add..5a1fe9d57 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 @@ -85,7 +85,7 @@ internal fun format(value: Double, digits: Int = 4): String = buildString { internal fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape - val linearStructure = this@toPrettyString.indices + val linearStructure = this@toPrettyString.shapeIndices val vectorSize = shape.last() append("DoubleTensor(\n") var charOffset = 3 diff --git a/settings.gradle.kts b/settings.gradle.kts index e73381bf2..889855eef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,8 +5,8 @@ pluginManagement { gradlePluginPortal() } - val kotlinVersion = "1.6.0-RC" - val toolsVersion = "0.10.5" + val kotlinVersion = "1.6.0-RC2" + val toolsVersion = "0.10.6" plugins { id("org.jetbrains.kotlinx.benchmark") version "0.3.1" From a1351aa9428b44965bdcb811a96115dbaca9c8ab Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Nov 2021 17:50:49 +0300 Subject: [PATCH 02/72] Buffer views --- .../space/kscience/kmath/fit/chiSquared.kt | 4 +- .../kotlin/space/kscience/kmath/fit/qowFit.kt | 4 +- .../space/kscience/kmath/series/analyzeDif.kt | 44 ++-- .../random/CMRandomGeneratorWrapper.kt | 5 +- .../commons/transform/Transformations.kt | 6 +- .../commons/optimization/OptimizeTest.kt | 2 +- .../kmath/domains/HyperSquareDomain.kt | 1 + .../kmath/expressions/specialExpressions.kt | 3 +- .../kmath/linear/BufferedLinearSpace.kt | 1 + .../space/kscience/kmath/nd/Structure1D.kt | 2 +- .../kmath/operations/BufferAlgebra.kt | 7 +- .../kmath/operations/DoubleBufferOps.kt | 5 +- .../space/kscience/kmath/structures/Buffer.kt | 20 +- .../kscience/kmath/structures/BufferView.kt | 140 ++++++++++++ .../kscience/kmath/structures/DoubleBuffer.kt | 2 +- .../kscience/kmath/structures/FloatBuffer.kt | 2 +- .../kscience/kmath/structures/IntBuffer.kt | 2 +- .../kscience/kmath/structures/LongBuffer.kt | 2 +- .../kmath/structures/MutableBuffer.kt | 5 +- .../bufferExtensions.kt} | 39 +++- .../kmath/structures/BufferExpandedTest.kt | 27 +++ .../kmath/streaming/RingBufferTest.kt | 2 +- .../space/kscience/kmath/real/RealMatrix.kt | 2 +- .../space/kscience/kmath/real/RealVector.kt | 1 + .../kmath/integration/GaussIntegrator.kt | 1 + .../integration/GaussIntegratorRuleFactory.kt | 2 +- .../kmath/integration/SplineIntegrator.kt | 6 +- .../kscience/kmath/geometry/Vector2DTest.kt | 3 +- .../kscience/kmath/geometry/Vector3DTest.kt | 2 +- .../kmath/histogram/UnivariateHistogram.kt | 2 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 2 +- .../kmath/distributions/Distribution.kt | 2 +- .../kmath/distributions/NormalDistribution.kt | 2 +- .../UniformDistribution.kt | 5 +- .../AhrensDieterExponentialSampler.kt | 3 +- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 2 - .../samplers/AliasMethodDiscreteSampler.kt | 2 - .../{internal => samplers}/InternalErf.kt | 2 +- .../{internal => samplers}/InternalGamma.kt | 2 +- .../{internal => samplers}/InternalUtils.kt | 2 +- .../samplers/KempSmallMeanPoissonSampler.kt | 1 - .../samplers/NormalizedGaussianSampler.kt | 1 - .../kscience/kmath/samplers/PoissonSampler.kt | 2 - .../kmath/{stat => samplers}/Sampler.kt | 8 +- .../{stat => samplers}/SamplerAlgebra.kt | 3 +- .../kscience/kmath/series/SeriesAlgebra.kt | 210 +++++++++++------- .../kscience/kmath/series/seriesExtensions.kt | 97 ++++++++ .../kotlin/space/kscience/kmath/stat/Mean.kt | 1 + .../space/kscience/kmath/stat/Median.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Rank.kt | 28 +++ .../kscience/kmath/stat/StatisticalAlgebra.kt | 59 +++++ .../space/kscience/kmath/stat/SamplerTest.kt | 2 + .../kmath/tensors/core/DoubleTensorAlgebra.kt | 1 + .../kmath/tensors/core/internal/linUtils.kt | 2 +- .../kmath/tensors/core/internal/utils.kt | 1 - 55 files changed, 610 insertions(+), 176 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/{operations/bufferOperation.kt => structures/bufferExtensions.kt} (73%) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => distributions}/UniformDistribution.kt (86%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{internal => samplers}/InternalErf.kt (93%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{internal => samplers}/InternalGamma.kt (99%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{internal => samplers}/InternalUtils.kt (98%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => samplers}/Sampler.kt (86%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => samplers}/SamplerAlgebra.kt (95%) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt 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 dbe0b8454..45678c425 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -12,8 +12,6 @@ import space.kscience.kmath.commons.optimization.CMOptimizer import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.asIterable -import space.kscience.kmath.operations.toList import space.kscience.kmath.optimization.FunctionOptimizationTarget import space.kscience.kmath.optimization.optimizeWith import space.kscience.kmath.optimization.resultPoint @@ -22,6 +20,8 @@ import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.toList import space.kscience.plotly.* import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.TraceValues 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..04764d763 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -13,8 +13,6 @@ import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.binding import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.asIterable -import space.kscience.kmath.operations.toList import space.kscience.kmath.optimization.QowOptimizer import space.kscience.kmath.optimization.chiSquaredOrNull import space.kscience.kmath.optimization.fitWith @@ -22,6 +20,8 @@ import space.kscience.kmath.optimization.resultPoint import space.kscience.kmath.real.map import space.kscience.kmath.real.step import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.toList import space.kscience.plotly.* import space.kscience.plotly.models.ScatterMode import kotlin.math.abs diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index 466aa2039..d67d59bfc 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -1,37 +1,43 @@ package space.kscience.kmath.series -import net.jafama.StrictFastMath.abs +import kotlinx.html.FlowContent +import kotlinx.html.h1 import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.toList import space.kscience.kmath.structures.Buffer -import space.kscience.plotly.Plotly -import space.kscience.plotly.makeFile -import space.kscience.plotly.scatter +import space.kscience.kmath.structures.toList +import space.kscience.plotly.* import kotlin.math.PI -import kotlin.math.max -fun main() = Double.algebra.bufferAlgebra.seriesAlgebra(0..100).invoke { - fun Buffer.plot() { - val ls = labels - Plotly.plot { +fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + fun FlowContent.plotSeries(buffer: Buffer) { + val ls = buffer.labels + plot { scatter { x.numbers = ls - y.numbers = toList() + y.numbers = buffer.toList() } - }.makeFile() + layout { + xaxis { + range(0.0..100.0) + } + } + } } - val s1 = series(100) { sin(2 * PI * it / 100) } - val s2 = series(100) { 1.0 } + val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 } + val s2 = s1.slice(20..50).moveTo(40) - (s1 - s2).plot() - - // Kolmogorov-Smirnov test statistic - val kst = (s1 - s2).fold(0.0) { sup, arg -> max(sup, abs(arg))} + val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 + val s4 = ln(s3) + Plotly.page { + h1 { +"This is my plot" } + plotSeries(s1) + plotSeries(s2) + plotSeries(s4) + }.makeFile() } \ No newline at end of file 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 28294cf14..2183399ef 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 @@ -7,10 +7,11 @@ package space.kscience.kmath.commons.random import kotlinx.coroutines.runBlocking import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.misc.toIntExact +import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.samplers.next import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.next + public class CMRandomGeneratorWrapper( public val factory: (IntArray) -> RandomGenerator, 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 73ab91542..3ac278ca0 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 @@ -10,13 +10,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import org.apache.commons.math3.transform.* import space.kscience.kmath.complex.Complex -import space.kscience.kmath.operations.SuspendBufferTransform import space.kscience.kmath.streaming.chunked import space.kscience.kmath.streaming.spread -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.* /** 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 c670ceead..681ec9ebc 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 @@ -13,11 +13,11 @@ import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.y import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.map import space.kscience.kmath.optimization.* import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.map import kotlin.math.pow import kotlin.test.Test 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 2b288172a..7ea3e22c4 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.domains import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices /** * 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 d68869491..6b17dfca5 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 @@ -6,8 +6,9 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.indices import kotlin.jvm.JvmName /** 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 7674012e6..bc736fc50 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 @@ -13,6 +13,7 @@ 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>( 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 3dcc77334..f2a4336eb 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 @@ -6,10 +6,10 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.asMutableBuffer +import space.kscience.kmath.structures.asSequence import kotlin.jvm.JvmInline /** 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 634a115c7..17c26ad11 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 @@ -8,7 +8,6 @@ package space.kscience.kmath.operations 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.ShortBuffer public interface WithSize { @@ -183,7 +182,7 @@ public class BufferField>( /** * Generate full buffer field from given buffer operations */ -public fun > BufferFieldOps.withSize(size: Int): BufferField = +public fun > BufferAlgebra.withSize(size: Int): BufferField = BufferField(elementAlgebra, bufferFactory, size) //Double buffer specialization @@ -196,6 +195,4 @@ public fun BufferField.buffer(vararg elements: Number): Buffer> A.bufferAlgebra(bufferFactory: BufferFactory): BufferFieldOps = BufferFieldOps(this, bufferFactory) -public val DoubleField.bufferAlgebra: BufferFieldOps - get() = BufferFieldOps(DoubleField, ::DoubleBuffer) - +public val DoubleField.bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps 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 b0cce91d3..269823a10 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 @@ -7,10 +7,7 @@ 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.asBuffer +import space.kscience.kmath.structures.* import kotlin.math.* 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 2c34327b5..91b4ee71b 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.structures -import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.operations.WithSize import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -30,11 +30,11 @@ public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer * * @param T the type of elements contained in the buffer. */ -public interface Buffer { +public interface Buffer : WithSize { /** * The size of this buffer. */ - public val size: Int + override val size: Int /** * Gets element at given index. @@ -44,15 +44,10 @@ public interface Buffer { /** * Iterates over all elements. */ - public operator fun iterator(): Iterator + public operator fun iterator(): Iterator = indices.asSequence().map(::get).iterator() override fun toString(): String - /** - * Returns an [IntRange] of the valid indices for this [Buffer]. - */ - public val indices: IntRange get() = 0 until size - public companion object { public fun toString(buffer: Buffer<*>): String = @@ -105,7 +100,12 @@ public interface Buffer { } } -public operator fun Buffer.get(index: UInt): T = get(index.toInt()) +/** + * Returns an [IntRange] of the valid indices for this [Buffer]. + */ +public val Buffer.indices: IntRange get() = 0 until size + +public operator fun Buffer.get(index: UInt): T = get(index.toInt()) /** * if index is in range of buffer, return the value. Otherwise, return null. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt new file mode 100644 index 000000000..d4e6a4a58 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -0,0 +1,140 @@ +package space.kscience.kmath.structures + +import space.kscience.kmath.misc.UnstableKMathAPI + +/** + * A buffer that wraps an original buffer + */ +public interface BufferView : Buffer { + public val origin: Buffer + + /** + * Get the index in [origin] buffer from index in this buffer. + * Return -1 if element not present in the original buffer + * This method should be used internally to optimize non-boxing access. + */ + @UnstableKMathAPI + public fun originIndex(index: Int): Int +} + +/** + * A zero-copy buffer that "sees" only part of original buffer. Slice can't go beyond original buffer borders. + */ +public class BufferSlice( + override val origin: Buffer, + public val offset: UInt = 0U, + override val size: Int, +) : BufferView { + + init { + require(size > 0) { "Size must be positive" } + require(offset + size.toUInt() <= origin.size.toUInt()) { + "End of buffer ${offset + size.toUInt()} is beyond the end of origin buffer size ${origin.size}" + } + } + + override fun get(index: Int): T = if (index >= size) { + throw IndexOutOfBoundsException("$index is out of ${0 until size} rage") + } else { + origin[index.toUInt() + offset] + } + + override fun iterator(): Iterator = + (offset until (offset + size.toUInt())).asSequence().map { origin[it] }.iterator() + + @UnstableKMathAPI + override fun originIndex(index: Int): Int = if (index >= size) -1 else index - offset.toInt() + + override fun toString(): String = "$origin[$offset..${offset + size.toUInt()}" +} + +/** + * An expanded buffer that could include the whole initial buffer ot its part and fills all space beyond it borders with [defaultValue]. + * + * The [offset] parameter shows the shift of expanded buffer start relative to origin start and could be both positive and negative. + */ +public class BufferExpanded( + override val origin: Buffer, + public val defaultValue: T, + public val offset: Int = 0, + override val size: Int = origin.size, +) : BufferView { + + init { + require(size > 0) { "Size must be positive" } + } + + override fun get(index: Int): T = when (index) { + !in 0 until size -> throw IndexOutOfBoundsException("Index $index is not in $indices") + in -offset until origin.size - offset -> origin[index + offset] + else -> defaultValue + } + + @UnstableKMathAPI + override fun originIndex(index: Int): Int = if (index in -offset until origin.size - offset) index + offset else -1 + + override fun toString(): String = "$origin[$offset..${offset + size}]" +} + +/** + * Zero-copy select a slice inside the original buffer + */ +public fun Buffer.slice(range: UIntRange): BufferView = BufferSlice( + this, + range.first, + (range.last - range.first).toInt() + 1 +) + +/** + * Resize original buffer to a given range using given [range], filling additional segments with [defaultValue]. + * Range left border could be negative to designate adding new blank segment to the beginning of the buffer + */ +public fun Buffer.expand( + range: IntRange, + defaultValue: T, +): BufferView = if (range.first >= 0 && range.last < size) { + BufferSlice( + this, + range.first.toUInt(), + (range.last - range.first) + 1 + ) +} else { + BufferExpanded( + this, + defaultValue, + range.first, + (range.last - range.first) + 1 + ) +} + +/** + * A [BufferView] that overrides indexing of the original buffer + */ +public class PermutatedBuffer( + override val origin: Buffer, + private val permutations: IntArray, +) : BufferView { + init { + permutations.forEach { index -> + if (index !in origin.indices) { + throw IndexOutOfBoundsException("Index $index is not in ${origin.indices}") + } + } + } + + override val size: Int get() = permutations.size + + override fun get(index: Int): T = origin[permutations[index]] + + override fun iterator(): Iterator = permutations.asSequence().map { origin[it] }.iterator() + + @UnstableKMathAPI + override fun originIndex(index: Int): Int = if (index in permutations.indices) permutations[index] else -1 + + override fun toString(): String = Buffer.toString(this) +} + +/** + * Created a permuted view of given buffer using provided [indices] + */ +public fun Buffer.view(indices: IntArray): PermutatedBuffer = PermutatedBuffer(this, indices) \ No newline at end of file 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 3b554ab07..087f81934 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 @@ -13,7 +13,7 @@ import kotlin.jvm.JvmInline * @property array the underlying array. */ @JvmInline -public value class DoubleBuffer(public val array: DoubleArray) : MutableBuffer { +public value class DoubleBuffer(public val array: DoubleArray) : PrimitiveBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Double = array[index] 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 dc7903cbf..f99e73baa 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 @@ -14,7 +14,7 @@ import kotlin.jvm.JvmInline * @author Iaroslav Postovalov */ @JvmInline -public value class FloatBuffer(public val array: FloatArray) : MutableBuffer { +public value class FloatBuffer(public val array: FloatArray) : PrimitiveBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Float = array[index] 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 ca078746c..1de36453f 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 @@ -13,7 +13,7 @@ import kotlin.jvm.JvmInline * @property array the underlying array. */ @JvmInline -public value class IntBuffer(public val array: IntArray) : MutableBuffer { +public value class IntBuffer(public val array: IntArray) : PrimitiveBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Int = array[index] 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 a0b5c78fa..0596729b4 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 @@ -13,7 +13,7 @@ import kotlin.jvm.JvmInline * @property array the underlying array. */ @JvmInline -public value class LongBuffer(public val array: LongArray) : MutableBuffer { +public value class LongBuffer(public val array: LongArray) : PrimitiveBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Long = array[index] 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 97185b918..396d51bc3 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 @@ -94,4 +94,7 @@ public interface MutableBuffer : Buffer { public inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = auto(T::class, size, initializer) } -} \ No newline at end of file +} + + +public sealed interface PrimitiveBuffer: MutableBuffer \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt similarity index 73% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt index 115f8c23a..f8b785724 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt @@ -3,10 +3,9 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.operations +package space.kscience.kmath.structures import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.structures.* /** * Typealias for buffer transformations. @@ -103,4 +102,40 @@ public inline fun Buffer.zip( ): Buffer { require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" } return bufferFactory(size) { transform(get(it), other[it]) } +} + +/** + * Simular to https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/binary-search.html. + * The implementation is copied from Kotlin stdlib + */ +public fun > Buffer.binarySearch(element: T, fromIndex: Int = 0, toIndex: Int = size): Int { + var low = fromIndex + var high = toIndex - 1 + + while (low <= high) { + val mid = (low + high).ushr(1) // safe from overflows + val midVal = get(mid) + val cmp = compareValues(midVal, element) + + when { + cmp < 0 -> low = mid + 1 + cmp > 0 -> high = mid - 1 + else -> return mid // key found + } + } + return -(low + 1) // key not found +} + +/** + * Create a buffer containing sorted elements of this buffer. + */ +@Suppress("CAST_NEVER_SUCCEEDS") +public fun > Buffer.sorted(): Buffer = when (this) { + is PrimitiveBuffer -> when (this) { + is LongBuffer -> toLongArray().apply { sort() } as Buffer + is FloatBuffer -> toFloatArray().apply { sort() } as Buffer + is IntBuffer -> toIntArray().apply { sort() } as Buffer + is DoubleBuffer -> toDoubleArray().apply { sort() } as Buffer + } + else -> asIterable().sorted().asBuffer() } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt new file mode 100644 index 000000000..992080fb0 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt @@ -0,0 +1,27 @@ +package space.kscience.kmath.structures + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFails + +internal class BufferExpandedTest { + private val buffer = (0..100).toList().asBuffer() + + @Test + fun shrink(){ + val view = buffer.slice(20U..30U) + assertEquals(20, view[0]) + assertEquals(30, view[10]) + assertFails { view[11] } + } + + @Test + fun expandNegative(){ + val view: BufferView = buffer.expand(-20..113,0) + assertEquals(0,view[4]) + assertEquals(0,view[123]) + assertEquals(100, view[120]) + assertFails { view[-2] } + assertFails { view[134] } + } +} \ No newline at end of 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 a3143a1ac..14081b0f5 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.streaming import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking -import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.structures.asSequence import kotlin.test.Test import kotlin.test.assertEquals 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 c1ee8b48f..88932d59b 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 @@ -13,9 +13,9 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.algebra -import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asIterable import kotlin.math.pow /* diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index b108f696e..cca1c3551 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -11,6 +11,7 @@ import space.kscience.kmath.operations.DoubleL2Norm import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer.Companion.double import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices import kotlin.math.pow public typealias DoubleVector = Point 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 9ee292998..2b426d204 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 @@ -8,6 +8,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices /** * A simple one-pass integrator based on Gauss rule 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 94c73832b..b09129626 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 @@ -5,10 +5,10 @@ package space.kscience.kmath.integration -import space.kscience.kmath.operations.map import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.map import kotlin.jvm.Synchronized import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal 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 6abe89aad..662cdf3d7 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 @@ -12,10 +12,14 @@ import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.sum import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.map /** * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact 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 89ee23354..6f4a9e2ed 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,6 +1,7 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.operations.toList + +import space.kscience.kmath.structures.toList import kotlin.test.Test import kotlin.test.assertEquals 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 70f8f4ebd..717e78871 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,6 +1,6 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.operations.toList +import space.kscience.kmath.structures.toList import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index d5b74fb9b..018f47a7f 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence @UnstableKMathAPI 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 9731908b3..e646d2bd0 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 @@ -21,9 +21,9 @@ import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.asSequence import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence /** * A function for conversion of number to MST for pretty print 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 298bbc858..1cff271a7 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain +import space.kscience.kmath.samplers.Sampler import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler /** * A distribution of typed objects. 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 24429cf32..8f9250ee5 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain -import space.kscience.kmath.internal.InternalErf import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.samplers.InternalErf import space.kscience.kmath.samplers.NormalizedGaussianSampler import space.kscience.kmath.samplers.ZigguratNormalizedGaussianSampler import space.kscience.kmath.stat.RandomGenerator diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt similarity index 86% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt index 4c0d08720..fd9fa0bdd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt @@ -3,12 +3,11 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain -import space.kscience.kmath.distributions.Distribution -import space.kscience.kmath.distributions.UnivariateDistribution +import space.kscience.kmath.stat.RandomGenerator public class UniformDistribution(public val range: ClosedFloatingPointRange) : UnivariateDistribution { private val length: Double = range.endInclusive - range.start 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 5f923fe5f..fd8437191 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.ln import kotlin.math.pow @@ -67,7 +66,7 @@ public class AhrensDieterExponentialSampler(public val mean: Double) : Sampler - qi += ln2.pow(i + 1.0) / space.kscience.kmath.internal.InternalUtils.factorial(i + 1) + qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1) qi } } 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 063e055ce..fdba8ec90 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 @@ -7,9 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler import space.kscience.kmath.stat.chain -import space.kscience.kmath.stat.next import kotlin.math.* /** 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 b00db5b30..03ba142b7 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 @@ -6,9 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain -import space.kscience.kmath.internal.InternalUtils import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler import space.kscience.kmath.stat.chain import kotlin.math.ceil import kotlin.math.max diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalErf.kt similarity index 93% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalErf.kt index 5b3cb1859..b8f9fd25e 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalErf.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.internal +package space.kscience.kmath.samplers import kotlin.math.abs diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalGamma.kt similarity index 99% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalGamma.kt index 18abd669f..cdc40b44d 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalGamma.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.internal +package space.kscience.kmath.samplers import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalUtils.kt similarity index 98% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalUtils.kt index 77ba02a25..b0c63ff15 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/InternalUtils.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.internal +package space.kscience.kmath.samplers import kotlin.math.ln import kotlin.math.min 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 16f91570f..5146169a3 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.IntBuffer import kotlin.math.exp 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 ceb324e8d..d427d8e7a 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler public interface BlockingDoubleSampler: Sampler{ override fun sample(generator: RandomGenerator): BlockingDoubleChain 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 d3ff05b06..3504a65bf 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 @@ -6,10 +6,8 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain -import space.kscience.kmath.internal.InternalUtils import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.IntBuffer import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt similarity index 86% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt index 0b3b52cab..2c842ab65 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt @@ -3,12 +3,16 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.samplers import kotlinx.coroutines.flow.first import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collect -import space.kscience.kmath.structures.* +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.IntBuffer import kotlin.jvm.JvmName /** diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt similarity index 95% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt index e0be72d4b..c0b8e5b5c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.ConstantChain @@ -12,6 +12,7 @@ import space.kscience.kmath.chains.zip import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke +import space.kscience.kmath.stat.RandomGenerator /** * Implements [Sampler] by sampling only certain [value]. diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 3bf8c66b3..ae1bfe0e7 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -1,80 +1,125 @@ package space.kscience.kmath.series -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.BufferAlgebra +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.RingOps +import space.kscience.kmath.stat.StatisticalAlgebra import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.getOrNull +import space.kscience.kmath.structures.BufferView import kotlin.math.max import kotlin.math.min -private fun IntRange.intersect(other: IntRange): IntRange = +@PublishedApi +internal fun IntRange.intersect(other: IntRange): IntRange = max(first, other.first)..min(last, other.last) -private val IntRange.size get() = last - first + 1 +@PublishedApi +internal val IntRange.size + get() = last - first + 1 + +@PublishedApi +internal operator fun IntRange.contains(other: IntRange): Boolean = (other.first in this) && (other.last in this) + +//TODO add permutated buffer +//TODO add rank function + + +public interface Series : Buffer { + public val origin: Buffer + /** + * Absolute position of start of this [Series] in [SeriesAlgebra] + */ + public val position: Int +} + +public val Series.absoluteIndices: IntRange get() = position until position + size + +/** + * A [BufferView] with index offset (both positive and negative) and possible size change + */ +private class OffsetBufer( + override val origin: Buffer, + override val position: Int, + override val size: Int = origin.size, +) : Series, Buffer by origin { -private class BufferView(val buffer: Buffer, val offset: Int, override val size: Int) : Buffer { init { - require(offset >= 0) { " Range offset must be positive" } - require(offset < buffer.size) { "Range offset is beyond the buffer size" } require(size > 0) { "Size must be positive" } - require(size < buffer.size) { "Slice size is larger than the buffer" } + require(size <= origin.size) { "Slice size is larger than the original buffer" } } - override fun get(index: Int): T = buffer[index - offset] - - override fun iterator(): Iterator = buffer.asSequence().drop(offset).take(size).iterator() - - override fun toString(): String = "$buffer[${offset}:${offset + size - 1}]" - - override val indices: IntRange = offset until offset + size + override fun toString(): String = "$origin-->${position}" } /** * A scope to operation on series */ -public class SeriesAlgebra, L>( - public val bufferAlgebra: BufferRingOps, +public class SeriesAlgebra, out BA : BufferAlgebra, L>( + override val bufferAlgebra: BA, private val labelResolver: (Int) -> L, -) : RingOps> { +) : RingOps>, StatisticalAlgebra { - public val elementAlgebra: A get() = bufferAlgebra.elementAlgebra - public val bufferFactory: BufferFactory get() = bufferAlgebra.bufferFactory + public val Buffer.indices: IntRange + get() = if (this is Series) { + absoluteIndices + } else { + 0 until size + } - public val Buffer.offset: UInt get() = indices.first.toUInt() + /** + * Get the value by absolute index in the series algebra or return null if index is out of range + */ + public fun Buffer.getAbsoluteOrNull(index: Int): T? = when { + index !in indices -> null + this is Series -> origin[index - position] + else -> get(index) + } + + /** + * Get the value by absolute index in the series algebra or throw [IndexOutOfBoundsException] if index is out of range + */ + public fun Buffer.getAbsolute(index: Int): T = + getAbsoluteOrNull(index) ?: throw IndexOutOfBoundsException("Index $index is not in $indices") + + /** + * Create an offset series with index starting point at [index] + */ + public fun Buffer.moveTo(index: Int): Series = if (this is Series) { + OffsetBufer(origin, index, size) + } else { + OffsetBufer(this, index, size) + } + + /** + * Create a buffer view using given absolute range + */ + public fun Buffer.slice(range: IntRange): Series { + val size = range.size + return if (this is Series) { + OffsetBufer(this, indices.first + range.first, size) + } else { + OffsetBufer(this, range.first, size) + } + } + + public fun Buffer.expand(range: IntRange, defaultValue: T): Series = if (range in indices) { + slice(range) + } else { + TODO() + } + + public val Buffer.offset: Int get() = if (this is Series) position else 0 /** * Build a new series */ - public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Buffer { + public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Series { return bufferFactory(size) { val index = it + fromIndex elementAlgebra.block(labelResolver(index)) }.moveTo(fromIndex) } - /** - * Move a series starting to start at a given index - */ - public fun Buffer.moveTo(index: Int): Buffer = if (index == 0) { - this - } else if (this is BufferView) { - BufferView(buffer, index.toInt(), size) - } else { - BufferView(this, index.toInt(), size) - } - - /** - * Create a buffer view using given range - */ - public fun Buffer.get(range: IntRange): Buffer { - val size = range.size - return if (this is BufferView) { - BufferView(this, indices.first + range.first, size) - } else { - BufferView(this, range.first, size) - } - } - /** * Get a label buffer for given buffer. */ @@ -87,34 +132,15 @@ public class SeriesAlgebra, L>( public operator fun Buffer.get(label: L): T? { val index = labels.indexOf(label) if (index == -1) return null - return get(index + offset.toInt()) - } - - override fun add(left: Buffer, right: Buffer): Buffer = elementAlgebra.invoke { - val newRange = left.indices.intersect(right.indices) - //TODO optimize copy at BufferAlgebra level - bufferFactory(newRange.size) { - val offset = it + newRange.first - left[offset] + right[offset] - }.moveTo(newRange.first) - } - - override fun Buffer.unaryMinus(): Buffer = map { -it } - - override fun multiply(left: Buffer, right: Buffer): Buffer = elementAlgebra.invoke { - val newRange = left.indices.intersect(right.indices) - bufferFactory(newRange.size) { - val offset = it + newRange.first - left[offset] * right[offset] - } + return getAbsolute(index + offset.toInt()) } /** * Map a series to another series of the same size */ - public inline fun Buffer.map(crossinline transform: A.(T) -> T): Buffer { + public inline fun Buffer.map(crossinline transform: A.(T) -> T): Series { val buf = bufferFactory(size) { - elementAlgebra.transform(get(it)) + elementAlgebra.transform(getAbsolute(it)) } return buf.moveTo(indices.first) } @@ -122,49 +148,63 @@ public class SeriesAlgebra, L>( /** * Map series to another series of the same size with label */ - public inline fun Buffer.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Buffer { + public inline fun Buffer.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Series { val labels = labels val buf = bufferFactory(size) { - elementAlgebra.transform(get(it), labels[it]) + elementAlgebra.transform(getAbsolute(it), labels[it]) } return buf.moveTo(indices.first) } public inline fun Buffer.fold(initial: R, operation: A.(acc: R, T) -> R): R { var accumulator = initial - for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, get(index)) + for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) return accumulator } public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { val labels = labels var accumulator = initial - for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, get(index), labels[index]) + for (index in this.indices) accumulator = + elementAlgebra.operation(accumulator, getAbsolute(index), labels[index]) return accumulator } /** - * Zip two buffers replacing missing values with [defaultValue] + * Zip two buffers in the range whe they overlap */ public inline fun Buffer.zip( other: Buffer, - defaultValue: T, - crossinline operation: A.(left: T?, right: T?) -> T?, - ): Buffer { - val start = min(indices.first, other.indices.first) - val size = max(indices.last, other.indices.last) - start - return bufferFactory(size) { + crossinline operation: A.(left: T, right: T) -> T, + ): Series { + val newRange = indices.intersect(other.indices) + return bufferFactory(newRange.size) { elementAlgebra.operation( - getOrNull(it) ?: defaultValue, - other.getOrNull(it) ?: defaultValue - ) ?: defaultValue - } + getAbsolute(it), + other.getAbsolute(it) + ) + }.moveTo(newRange.first) } + + override fun Buffer.unaryMinus(): Buffer = map { -it } + + override fun add(left: Buffer, right: Buffer): Series = left.zip(right) { l, r -> l + r } + + override fun multiply(left: Buffer, right: Buffer): Buffer = left.zip(right) { l, r -> l * r } } -public fun , L> BufferRingOps.seriesAlgebra(labels: Iterable): SeriesAlgebra { +public fun , BA : BufferAlgebra, L> BA.seriesAlgebra(labels: Iterable): SeriesAlgebra { val l = labels.toList() return SeriesAlgebra(this) { if (it in l.indices) l[it] else error("Index $it is outside of labels range ${l.indices}") } -} \ No newline at end of file +} + +public fun , BA : BufferAlgebra, L> BA.seriesAlgebra(labelGenerator: (Int) -> L): SeriesAlgebra = + SeriesAlgebra(this, labelGenerator) + +/** + * Create a series algebra using offset as a label + */ +public fun , BA : BufferAlgebra> BA.seriesAlgebra(): SeriesAlgebra = + SeriesAlgebra(this) { it } \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt new file mode 100644 index 000000000..882fa2c46 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt @@ -0,0 +1,97 @@ +package space.kscience.kmath.series + +import space.kscience.kmath.operations.BufferAlgebra +import space.kscience.kmath.operations.ExponentialOperations +import space.kscience.kmath.operations.PowerOperations +import space.kscience.kmath.operations.TrigonometricOperations +import space.kscience.kmath.structures.Buffer + + +//trigonometric + +public fun SeriesAlgebra.sin( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.sin(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.cos( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.cos(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.tan( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.tan(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.asin( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.asin(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.acos( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.acos(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.atan( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = + bufferAlgebra.atan(arg).moveTo(arg.offset) + + +//exponential + +public fun SeriesAlgebra.exp( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.exp(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.ln( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.ln(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.sinh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.sinh(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.cosh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.cosh(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.tanh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.tanh(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.asinh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.asinh(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.acosh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.acosh(arg).moveTo(arg.offset) + +public fun SeriesAlgebra.atanh( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : ExponentialOperations> = + bufferAlgebra.atanh(arg).moveTo(arg.offset) + + +//power + +public fun SeriesAlgebra.power( + arg: Buffer, + pow: Number, +): Series where BA : BufferAlgebra, BA : PowerOperations> = + bufferAlgebra.power(arg, pow).moveTo(arg.offset) + +public fun SeriesAlgebra.sqrt( + arg: Buffer, +): Series where BA : BufferAlgebra, BA : PowerOperations> = + bufferAlgebra.sqrt(arg).moveTo(arg.offset) \ No newline at end of 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 70da58171..f2658549a 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.stat import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices /** * Arithmetic mean 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 664e4e8e7..54b2e42b3 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 @@ -5,8 +5,8 @@ package space.kscience.kmath.stat -import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence /** * Non-composable median diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt new file mode 100644 index 000000000..92b7e1e7b --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt @@ -0,0 +1,28 @@ +package space.kscience.kmath.stat + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asIterable + +public class Rank>: BlockingStatistic { + override fun evaluateBlocking(data: Buffer): IntArray { + // https://www.geeksforgeeks.org/rank-elements-array/ + val permutations = ArrayList>(data.size) + data.asIterable().mapIndexedTo(permutations) { i, v -> v to i } + permutations.sortBy { it.first } + var rank = 1 + var i = 0 + val r = IntArray(data.size) { 0 } + while (i < data.size) { + var j = i + while (j < data.size - 1 && permutations[j].first == permutations[j + 1]) ++j + val n = j - i + 1 + (0 until n).map { k -> + val idx = permutations[i + k].second + r[idx] = rank + ((n - 1) * 0.5f).toInt() + } + rank += n + i += n + } + return r + } +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt new file mode 100644 index 000000000..c8510a8eb --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt @@ -0,0 +1,59 @@ +package space.kscience.kmath.stat + +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.sorted + +public interface StatisticalAlgebra, out BA : BufferAlgebra> : Algebra> { + public val bufferAlgebra: BA + public val elementAlgebra: A get() = bufferAlgebra.elementAlgebra + public val bufferFactory: BufferFactory get() = bufferAlgebra.bufferFactory +} + +/** + * Compute [empirical CDF function](https://en.wikipedia.org/wiki/Empirical_distribution_function) + */ +public fun > StatisticalAlgebra.ecdf(buffer: Buffer): (T) -> Double = { arg -> + buffer.asIterable().count { it < arg }.toDouble() / buffer.size +} + +/** + * Implementation copied from https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/index.html?org/apache/commons/math3/stat/inference/KolmogorovSmirnovTest.html + */ +public fun , A, BA : BufferAlgebra> StatisticalAlgebra.kolmogorovSmirnovTest( + x: Buffer, + y: Buffer, +): T where A : Group, A : NumericAlgebra = elementAlgebra.invoke { + // Copy and sort the sample arrays + val sx = x.sorted() + val sy = y.sorted() + val n = sx.size + val m = sy.size + + var rankX = 0 + var rankY = 0 + var curD: T = zero + + // Find the max difference between cdf_x and cdf_y + var supD: T = zero + do { + val z = if (sx[rankX] <= sy[rankY]) sx[rankX] else sy[rankY] + while (rankX < n && sx[rankX].compareTo(z) == 0) { + rankX += 1; + curD += number(m); + } + + while (rankY < m && sy[rankY].compareTo(z) == 0) { + rankY += 1; + curD -= number(n); + } + + when { + curD > supD -> supD = curD + -curD > supD -> supD = -curD + } + } while (rankX < n && rankY < m); + return supD; +} \ No newline at end of file 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 4060c0505..8a5148f9e 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 @@ -6,6 +6,8 @@ package space.kscience.kmath.stat import kotlinx.coroutines.runBlocking +import space.kscience.kmath.samplers.Sampler +import space.kscience.kmath.samplers.sampleBuffer import kotlin.test.Test class SamplerTest { 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 6c6264989..6f10ad7ad 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 @@ -15,6 +15,7 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.indices import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.Tensor 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 5a2e69c87..dbfa09cdf 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 @@ -12,9 +12,9 @@ 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.operations.invoke import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.asSequence import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra 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 5a1fe9d57..5ec2f240b 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 @@ -6,7 +6,6 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.as1D -import space.kscience.kmath.operations.toMutableList import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* From 1315a8cd34102e205d75af7af8fa7b06945772ee Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Nov 2021 19:57:22 +0300 Subject: [PATCH 03/72] views cleanup --- .../space/kscience/kmath/series/analyzeDif.kt | 3 ++- .../kscience/kmath/structures/BufferView.kt | 2 +- .../kscience/kmath/series/SeriesAlgebra.kt | 24 +++---------------- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index d67d59bfc..9b7493438 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -6,6 +6,7 @@ import kotlinx.html.h1 import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.slice import space.kscience.kmath.structures.toList import space.kscience.plotly.* import kotlin.math.PI @@ -28,7 +29,7 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 } - val s2 = s1.slice(20..50).moveTo(40) + val s2 = s1.slice(20U..50U).moveTo(40) val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s4 = ln(s3) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt index d4e6a4a58..d82efa865 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -137,4 +137,4 @@ public class PermutatedBuffer( /** * Created a permuted view of given buffer using provided [indices] */ -public fun Buffer.view(indices: IntArray): PermutatedBuffer = PermutatedBuffer(this, indices) \ No newline at end of file +public fun Buffer.permute(indices: IntArray): PermutatedBuffer = PermutatedBuffer(this, indices) \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index ae1bfe0e7..de72c7346 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -14,14 +14,14 @@ internal fun IntRange.intersect(other: IntRange): IntRange = max(first, other.first)..min(last, other.last) @PublishedApi -internal val IntRange.size +internal val IntRange.size: Int get() = last - first + 1 @PublishedApi internal operator fun IntRange.contains(other: IntRange): Boolean = (other.first in this) && (other.last in this) -//TODO add permutated buffer -//TODO add rank function +//TODO add permutation sort +//TODO check rank statistics public interface Series : Buffer { @@ -90,24 +90,6 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( OffsetBufer(this, index, size) } - /** - * Create a buffer view using given absolute range - */ - public fun Buffer.slice(range: IntRange): Series { - val size = range.size - return if (this is Series) { - OffsetBufer(this, indices.first + range.first, size) - } else { - OffsetBufer(this, range.first, size) - } - } - - public fun Buffer.expand(range: IntRange, defaultValue: T): Series = if (range in indices) { - slice(range) - } else { - TODO() - } - public val Buffer.offset: Int get() = if (this is Series) position else 0 /** From f6b576071dc2ef1c11d6b8ba1056f55065824d91 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 12:25:17 +0300 Subject: [PATCH 04/72] Add non-boxing BufferView access --- .../kmath/structures/bufferPrimitiveAccess.kt | 37 +++++++++++++++ .../kmath/{stat => random}/MCScope.kt | 2 +- .../kmath/{stat => random}/RandomChain.kt | 2 +- .../kmath/{stat => random}/RandomGenerator.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Rank.kt | 45 +++++++++++-------- 5 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => random}/MCScope.kt (98%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => random}/RandomChain.kt (97%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => random}/RandomGenerator.kt (99%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt new file mode 100644 index 000000000..0e465c64b --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt @@ -0,0 +1,37 @@ +package space.kscience.kmath.structures + +import space.kscience.kmath.misc.UnstableKMathAPI + +/** + * Non-boxing access to primitive [Double] + */ +@OptIn(UnstableKMathAPI::class) +public fun Buffer.getDouble(index: Int): Double = if (this is BufferView) { + val originIndex = originIndex(index) + if( originIndex>=0) { + origin.getDouble(originIndex) + } else { + get(index) + } +} else if (this is DoubleBuffer) { + array[index] +} else { + get(index) +} + +/** + * Non-boxing access to primitive [Int] + */ +@OptIn(UnstableKMathAPI::class) +public fun Buffer.getInt(index: Int): Int = if (this is BufferView) { + val originIndex = originIndex(index) + if( originIndex>=0) { + origin.getInt(originIndex) + } else { + get(index) + } +} else if (this is IntBuffer) { + array[index] +} else { + get(index) +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt similarity index 98% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt index 5e1e577ba..4fb7cb2fb 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.random import kotlinx.coroutines.* import kotlin.contracts.InvocationKind diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomChain.kt similarity index 97% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomChain.kt index 61e472334..aec85d9d5 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomChain.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.random import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomGenerator.kt similarity index 99% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomGenerator.kt index 98ee6402a..30b27e338 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/RandomGenerator.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ -package space.kscience.kmath.stat +package space.kscience.kmath.random import space.kscience.kmath.structures.DoubleBuffer import kotlin.random.Random diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt index 92b7e1e7b..5a5b99177 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt @@ -3,26 +3,33 @@ package space.kscience.kmath.stat import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asIterable -public class Rank>: BlockingStatistic { - override fun evaluateBlocking(data: Buffer): IntArray { - // https://www.geeksforgeeks.org/rank-elements-array/ - val permutations = ArrayList>(data.size) - data.asIterable().mapIndexedTo(permutations) { i, v -> v to i } - permutations.sortBy { it.first } - var rank = 1 - var i = 0 - val r = IntArray(data.size) { 0 } - while (i < data.size) { - var j = i - while (j < data.size - 1 && permutations[j].first == permutations[j + 1]) ++j - val n = j - i + 1 - (0 until n).map { k -> - val idx = permutations[i + k].second - r[idx] = rank + ((n - 1) * 0.5f).toInt() +/** + * Rank statistics + */ +public class Rank> : BlockingStatistic { + override fun evaluateBlocking(data: Buffer): IntArray = Companion.evaluate(data) + + public companion object { + public fun > evaluate(data: Buffer): IntArray { + // https://www.geeksforgeeks.org/rank-elements-array/ + val permutations = ArrayList>(data.size) + data.asIterable().mapIndexedTo(permutations) { i, v -> v to i } + permutations.sortBy { it.first } + var rank = 1 + var i = 0 + val r = IntArray(data.size) + while (i < data.size) { + var j = i + while (j < data.size - 1 && permutations[j].first == permutations[j + 1]) ++j + val n = j - i + 1 + (0 until n).map { k -> + val idx = permutations[i + k].second + r[idx] = rank + ((n - 1) * 0.5f).toInt() + } + rank += n + i += n } - rank += n - i += n + return r } - return r } } \ No newline at end of file From d62bc66d4ab24bdd240277a18c227f1adfee632d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 13:42:22 +0300 Subject: [PATCH 05/72] Refactoring --- .../kmath/benchmarks/BufferBenchmark.kt | 21 ++++++++++----- .../space/kscience/kmath/fit/chiSquared.kt | 2 +- .../kotlin/space/kscience/kmath/fit/qowFit.kt | 2 +- .../kmath/stat/DistributionBenchmark.kt | 1 + .../kscience/kmath/stat/DistributionDemo.kt | 1 + .../random/CMRandomGeneratorWrapper.kt | 2 +- .../commons/optimization/OptimizeTest.kt | 2 +- .../kmath/operations/BufferAlgebra.kt | 27 +++++++++---------- .../kmath/operations/DoubleBufferOps.kt | 9 +++++++ .../kmath/distributions/Distribution.kt | 2 +- .../distributions/FactorizedDistribution.kt | 2 +- .../kmath/distributions/NormalDistribution.kt | 2 +- .../distributions/UniformDistribution.kt | 2 +- .../space/kscience/kmath/random/MCScope.kt | 4 +++ .../AhrensDieterExponentialSampler.kt | 2 +- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 10 +++---- .../samplers/AliasMethodDiscreteSampler.kt | 4 +-- .../kmath/samplers/BoxMullerSampler.kt | 2 +- .../kmath/samplers/GaussianSampler.kt | 4 +-- .../samplers/KempSmallMeanPoissonSampler.kt | 2 +- .../MarsagliaNormalizedGaussianSampler.kt | 2 +- .../samplers/NormalizedGaussianSampler.kt | 6 ++--- .../kscience/kmath/samplers/PoissonSampler.kt | 2 +- .../space/kscience/kmath/samplers/Sampler.kt | 2 +- .../kscience/kmath/samplers/SamplerAlgebra.kt | 2 +- .../ZigguratNormalizedGaussianSampler.kt | 3 +-- .../kmath/stat/RandomSourceGenerator.kt | 6 ++++- .../kmath/stat/CommonsDistributionsTest.kt | 1 + .../space/kscience/kmath/stat/MCScopeTest.kt | 8 +++--- .../space/kscience/kmath/stat/SamplerTest.kt | 2 ++ .../kscience/kmath/stat/StatisticTest.kt | 2 ++ .../kmath/tensors/core/internal/utils.kt | 2 +- 32 files changed, 86 insertions(+), 55 deletions(-) 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 5cf194b67..f196e21c5 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -6,31 +6,38 @@ package space.kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.complex.Complex +import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.complex +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBuffer @State(Scope.Benchmark) internal class BufferBenchmark { @Benchmark - fun genericDoubleBufferReadWrite() { + fun genericDoubleBufferReadWrite(blackhole: Blackhole) { val buffer = DoubleBuffer(size) { it.toDouble() } - + var res = 0.0 (0 until size).forEach { - buffer[it] + res += buffer[it] } + blackhole.consume(res) } @Benchmark - fun complexBufferReadWrite() { - val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } + fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField { + val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } + var res = zero (0 until size / 2).forEach { - buffer[it] + res += buffer[it] } + + blackhole.consume(res) } private companion object { 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 45678c425..1325af0cd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -16,10 +16,10 @@ import space.kscience.kmath.optimization.FunctionOptimizationTarget import space.kscience.kmath.optimization.optimizeWith import space.kscience.kmath.optimization.resultPoint import space.kscience.kmath.optimization.resultValue +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step -import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.toList import space.kscience.plotly.* 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 04764d763..afb901c66 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -17,9 +17,9 @@ import space.kscience.kmath.optimization.QowOptimizer import space.kscience.kmath.optimization.chiSquaredOrNull import space.kscience.kmath.optimization.fitWith import space.kscience.kmath.optimization.resultPoint +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.map import space.kscience.kmath.real.step -import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.toList import space.kscience.plotly.* 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 732c9a8e3..a61247ce7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler import java.time.Duration import java.time.Instant 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 685214c39..8e3983160 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.runBlocking import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collectWithState import space.kscience.kmath.distributions.NormalDistribution +import space.kscience.kmath.random.RandomGenerator private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) 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 2183399ef..e5aefdee8 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 @@ -8,9 +8,9 @@ package space.kscience.kmath.commons.random import kotlinx.coroutines.runBlocking import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.toIntExact +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.samplers.next -import space.kscience.kmath.stat.RandomGenerator public class CMRandomGeneratorWrapper( 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 681ec9ebc..dddfc1063 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 @@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol.Companion.y import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol import space.kscience.kmath.optimization.* -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.map 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 17c26ad11..1beff450b 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 @@ -21,11 +21,6 @@ public interface BufferAlgebra> : Algebra> { public val elementAlgebra: A public val bufferFactory: 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] } - } - //TODO move to multi-receiver inline extension public fun Buffer.map(block: A.(T) -> T): Buffer = mapInline(this, block) @@ -49,12 +44,15 @@ public interface BufferAlgebra> : Algebra> { } } +public fun > BufferAlgebra.buffer(vararg elements: T): Buffer = + bufferFactory(elements.size) { elements[it] } + /** * Inline map */ private inline fun > BufferAlgebra.mapInline( buffer: Buffer, - crossinline block: A.(T) -> T + crossinline block: A.(T) -> T, ): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) } /** @@ -62,7 +60,7 @@ private inline fun > BufferAlgebra.mapInline( */ private inline fun > BufferAlgebra.mapIndexedInline( buffer: Buffer, - crossinline block: A.(index: Int, arg: T) -> T + crossinline block: A.(index: Int, arg: T) -> T, ): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) } /** @@ -71,7 +69,7 @@ private inline fun > BufferAlgebra.mapIndexedInline( private inline fun > BufferAlgebra.zipInline( l: Buffer, r: Buffer, - crossinline block: A.(l: T, r: T) -> T + 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]) } @@ -128,13 +126,13 @@ public fun > BufferAlgebra.atanh(arg: Buff mapInline(arg) { atanh(it) } public fun > BufferAlgebra.pow(arg: Buffer, pow: Number): Buffer = - mapInline(arg) {it.pow(pow) } + mapInline(arg) { it.pow(pow) } -public open class BufferRingOps>( +public open class BufferRingOps>( override val elementAlgebra: A, override val bufferFactory: BufferFactory, -) : BufferAlgebra, RingOps>{ +) : BufferAlgebra, RingOps> { 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 } @@ -155,7 +153,8 @@ public val ShortRing.bufferAlgebra: BufferRingOps public open class BufferFieldOps>( elementAlgebra: A, bufferFactory: BufferFactory, -) : BufferRingOps(elementAlgebra, bufferFactory), BufferAlgebra, FieldOps>, ScaleOperations> { +) : BufferRingOps(elementAlgebra, bufferFactory), BufferAlgebra, FieldOps>, + ScaleOperations> { 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 } @@ -172,7 +171,7 @@ public open class BufferFieldOps>( public class BufferField>( elementAlgebra: A, bufferFactory: BufferFactory, - override val size: Int + override val size: Int, ) : BufferFieldOps(elementAlgebra, bufferFactory), Field>, WithSize { override val zero: Buffer = bufferFactory(size) { elementAlgebra.zero } @@ -195,4 +194,4 @@ public fun BufferField.buffer(vararg elements: Number): Buffer> A.bufferAlgebra(bufferFactory: BufferFactory): BufferFieldOps = BufferFieldOps(this, bufferFactory) -public val DoubleField.bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps +public val DoubleField.bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps 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 269823a10..e11dc20ba 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 @@ -135,6 +135,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte override fun scale(a: Buffer, value: Double): DoubleBuffer = a.mapInline { it * value } public companion object : DoubleBufferOps() { + public inline fun Buffer.mapInline(block: (Double) -> Double): DoubleBuffer = if (this is DoubleBuffer) { DoubleArray(size) { block(array[it]) }.asBuffer() @@ -144,6 +145,14 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte } } +public inline fun BufferAlgebra.buffer(size: Int, init: (Int) -> Double): DoubleBuffer { + val res = DoubleArray(size) + for (i in 0 until size) { + res[i] = init(i) + } + return res.asBuffer() +} + public object DoubleL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.fold(0.0) { acc: Double, d: Double -> acc + d.pow(2) }) } 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 1cff271a7..13aab7b48 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.Sampler -import space.kscience.kmath.stat.RandomGenerator /** * A distribution of typed objects. 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 067b47796..af2d84ee5 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator /** * A multivariate distribution that takes a map of parameters. 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 8f9250ee5..0ef74ab87 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 @@ -6,11 +6,11 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.samplers.InternalErf import space.kscience.kmath.samplers.NormalizedGaussianSampler import space.kscience.kmath.samplers.ZigguratNormalizedGaussianSampler -import space.kscience.kmath.stat.RandomGenerator import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt index fd9fa0bdd..38ad1378e 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator public class UniformDistribution(public val range: ClosedFloatingPointRange) : UnivariateDistribution { private val length: Double = range.endInclusive - range.start diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt index 4fb7cb2fb..c7b1e69eb 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/random/MCScope.kt @@ -22,6 +22,10 @@ public class MCScope( public val random: RandomGenerator, ) +public fun MCScope.asCoroutineScope(): CoroutineScope = object : CoroutineScope { + override val coroutineContext: CoroutineContext get() = this@asCoroutineScope.coroutineContext +} + /** * Launches a supervised Monte-Carlo scope */ 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 fd8437191..04aaca232 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.ln import kotlin.math.pow 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 fdba8ec90..86e55985b 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.chain +import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.random.chain import kotlin.math.* /** @@ -23,14 +23,14 @@ import kotlin.math.* */ public class AhrensDieterMarsagliaTsangGammaSampler private constructor( alpha: Double, - theta: Double + theta: Double, ) : Sampler { private val delegate: BaseGammaSampler = if (alpha < 1) AhrensDieterGammaSampler(alpha, theta) else MarsagliaTsangGammaSampler(alpha, theta) private abstract class BaseGammaSampler internal constructor( protected val alpha: Double, - protected val theta: Double + protected val theta: Double, ) : Sampler { init { require(alpha > 0) { "alpha is not strictly positive: $alpha" } @@ -117,7 +117,7 @@ public class AhrensDieterMarsagliaTsangGammaSampler private constructor( public companion object { public fun of( alpha: Double, - theta: Double + theta: Double, ): Sampler = AhrensDieterMarsagliaTsangGammaSampler(alpha, theta) } } \ No newline at end of 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 03ba142b7..b36b0a86c 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.chain +import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.random.chain import kotlin.math.ceil import kotlin.math.max import kotlin.math.min 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 14aa26275..e448c2388 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.* 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 e5d1ecb49..fbd71c40a 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.chains.map -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator /** * Sampling from a Gaussian distribution with given mean and standard deviation. @@ -21,7 +21,7 @@ import space.kscience.kmath.stat.RandomGenerator public class GaussianSampler( public val mean: Double, public val standardDeviation: Double, - private val normalized: NormalizedGaussianSampler = BoxMullerSampler + private val normalized: NormalizedGaussianSampler = BoxMullerSampler, ) : BlockingDoubleSampler { init { 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 5146169a3..8dbadae8d 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.IntBuffer import kotlin.math.exp 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 5e636f246..47ca81940 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.ln import kotlin.math.sqrt 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 d427d8e7a..1d2cc1633 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 @@ -6,9 +6,9 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator -public interface BlockingDoubleSampler: Sampler{ +public interface BlockingDoubleSampler : Sampler { override fun sample(generator: RandomGenerator): BlockingDoubleChain } @@ -17,6 +17,6 @@ public interface BlockingDoubleSampler: Sampler{ * Marker interface for a sampler that generates values from an N(0,1) * [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution). */ -public fun interface NormalizedGaussianSampler : BlockingDoubleSampler{ +public fun interface NormalizedGaussianSampler : BlockingDoubleSampler { public companion object } 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 3504a65bf..75ec3a132 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.misc.toIntExact -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.IntBuffer import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt index 2c842ab65..7fa9ce875 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.samplers import kotlinx.coroutines.flow.first import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collect -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt index c0b8e5b5c..26ed72b06 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt @@ -12,7 +12,7 @@ import space.kscience.kmath.chains.zip import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator /** * Implements [Sampler] by sampling only certain [value]. 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 bda6f9819..5e5e7c49d 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 @@ -6,8 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.misc.toIntExact -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.* 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 a8e6a3362..0de9cff99 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 @@ -7,13 +7,17 @@ package space.kscience.kmath.stat import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource +import space.kscience.kmath.random.RandomGenerator /** * Implements [RandomGenerator] by delegating all operations to [RandomSource]. * * @property source the underlying [RandomSource] object. */ -public class RandomSourceGenerator internal constructor(public val source: RandomSource, seed: Long?) : RandomGenerator { +public class RandomSourceGenerator internal constructor( + public val source: RandomSource, + seed: Long?, +) : RandomGenerator { internal val random: UniformRandomProvider = seed?.let { RandomSource.create(source, seed) } ?: RandomSource.create(source) 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 2b6b1ca60..350409c6e 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 @@ -8,6 +8,7 @@ package space.kscience.kmath.stat import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler internal class CommonsDistributionsTest { 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 0c3d9cb0d..863bdf5ac 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 @@ -6,20 +6,22 @@ package space.kscience.kmath.stat import kotlinx.coroutines.* +import space.kscience.kmath.random.launch +import space.kscience.kmath.random.mcScope import java.util.* import kotlin.test.Test import kotlin.test.assertEquals data class RandomResult(val branch: String, val order: Int, val value: Int) -typealias ATest = suspend CoroutineScope.() -> Set +internal typealias ATest = suspend () -> Set -class MCScopeTest { +internal class MCScopeTest { val simpleTest: ATest = { mcScope(1111) { val res = Collections.synchronizedSet(HashSet()) - launch { + launch{ //println(random) repeat(10) { delay(10) 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 8a5148f9e..931ec99cb 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 @@ -6,6 +6,8 @@ package space.kscience.kmath.stat import kotlinx.coroutines.runBlocking +import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.random.chain import space.kscience.kmath.samplers.Sampler import space.kscience.kmath.samplers.sampleBuffer import kotlin.test.Test 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 777b93c29..e3ebcf559 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 @@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.take import kotlinx.coroutines.runBlocking +import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.random.chain import space.kscience.kmath.streaming.chunked import kotlin.test.Test import kotlin.test.assertEquals 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 5ec2f240b..c12374e88 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.as1D +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler -import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor From fa9ff4c9787ef18cacbcb4ea38aa30bedf7de681 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 17:56:53 +0300 Subject: [PATCH 06/72] Minor refactoring --- .../kmath/benchmarks/BufferBenchmark.kt | 36 ++++++++++++++++++- .../space/kscience/kmath/series/analyzeDif.kt | 3 ++ .../kscience/kmath/structures/BufferView.kt | 18 +++++++--- .../kmath/structures/bufferPrimitiveAccess.kt | 5 +-- .../kscience/kmath/stat/StatisticalAlgebra.kt | 25 ++++++++----- 5 files changed, 71 insertions(+), 16 deletions(-) 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 f196e21c5..6eb61e2fc 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -15,11 +15,24 @@ import space.kscience.kmath.complex.complex import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.getDouble +import space.kscience.kmath.structures.permute @State(Scope.Benchmark) internal class BufferBenchmark { + @Benchmark - fun genericDoubleBufferReadWrite(blackhole: Blackhole) { + fun doubleArrayReadWrite(blackhole: Blackhole) { + val buffer = DoubleArray(size) { it.toDouble() } + var res = 0.0 + (0 until size).forEach { + res += buffer[it] + } + blackhole.consume(res) + } + + @Benchmark + fun doubleBufferReadWrite(blackhole: Blackhole) { val buffer = DoubleBuffer(size) { it.toDouble() } var res = 0.0 (0 until size).forEach { @@ -28,6 +41,26 @@ internal class BufferBenchmark { blackhole.consume(res) } + @Benchmark + fun bufferViewReadWrite(blackhole: Blackhole) { + val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices) + var res = 0.0 + (0 until size).forEach { + res += buffer[it] + } + blackhole.consume(res) + } + + @Benchmark + fun bufferViewReadWriteSpecialized(blackhole: Blackhole) { + val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices) + var res = 0.0 + (0 until size).forEach { + res += buffer.getDouble(it) + } + blackhole.consume(res) + } + @Benchmark fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField { val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } @@ -42,5 +75,6 @@ internal class BufferBenchmark { private companion object { private const val size = 100 + private val reversedIndices = IntArray(size){it}.apply { reverse() } } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index 9b7493438..b9c3141dd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -5,6 +5,7 @@ import kotlinx.html.FlowContent import kotlinx.html.h1 import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.stat.ksComparisonStatistic import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.slice import space.kscience.kmath.structures.toList @@ -34,6 +35,8 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s4 = ln(s3) + val kmTest = ksComparisonStatistic(s1, s2) + Plotly.page { h1 { +"This is my plot" } plotSeries(s1) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt index d82efa865..8dc0d63ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -79,11 +79,19 @@ public class BufferExpanded( /** * Zero-copy select a slice inside the original buffer */ -public fun Buffer.slice(range: UIntRange): BufferView = BufferSlice( - this, - range.first, - (range.last - range.first).toInt() + 1 -) +public fun Buffer.slice(range: UIntRange): BufferView = if (this is BufferSlice) { + BufferSlice( + origin, + this.offset + range.first, + (range.last - range.first).toInt() + 1 + ) +} else { + BufferSlice( + this, + range.first, + (range.last - range.first).toInt() + 1 + ) +} /** * Resize original buffer to a given range using given [range], filling additional segments with [defaultValue]. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt index 0e465c64b..d361cb013 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt @@ -5,7 +5,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI /** * Non-boxing access to primitive [Double] */ -@OptIn(UnstableKMathAPI::class) + +@UnstableKMathAPI public fun Buffer.getDouble(index: Int): Double = if (this is BufferView) { val originIndex = originIndex(index) if( originIndex>=0) { @@ -22,7 +23,7 @@ public fun Buffer.getDouble(index: Int): Double = if (this is BufferView /** * Non-boxing access to primitive [Int] */ -@OptIn(UnstableKMathAPI::class) +@UnstableKMathAPI public fun Buffer.getInt(index: Int): Int = if (this is BufferView) { val originIndex = originIndex(index) if( originIndex>=0) { diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt index c8510a8eb..fcda58268 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.stat +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -20,12 +21,20 @@ public fun > StatisticalAlgebra.ecdf(buffer: Buffer>(val n: Int, val m: Int, val value: T) + +/** + * Kolmogorov-Smirnov sample comparison test * Implementation copied from https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/index.html?org/apache/commons/math3/stat/inference/KolmogorovSmirnovTest.html */ -public fun , A, BA : BufferAlgebra> StatisticalAlgebra.kolmogorovSmirnovTest( +@UnstableKMathAPI +public fun , A, BA : BufferAlgebra> StatisticalAlgebra.ksComparisonStatistic( x: Buffer, y: Buffer, -): T where A : Group, A : NumericAlgebra = elementAlgebra.invoke { +): KMComparisonResult where A : Group, A : NumericAlgebra = elementAlgebra.invoke { // Copy and sort the sample arrays val sx = x.sorted() val sy = y.sorted() @@ -41,19 +50,19 @@ public fun , A, BA : BufferAlgebra> StatisticalAlgebra supD -> supD = curD -curD > supD -> supD = -curD } - } while (rankX < n && rankY < m); - return supD; + } while (rankX < n && rankY < m) + return KMComparisonResult(n, m, supD) } \ No newline at end of file From 9a1f8a22661302e41a47e84dd52f2ea050d7b53c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 10 Nov 2021 11:51:20 +0300 Subject: [PATCH 07/72] remove unnecessary toInt --- .../kotlin/space/kscience/kmath/series/SeriesAlgebra.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index de72c7346..79da3d98d 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -26,6 +26,7 @@ internal operator fun IntRange.contains(other: IntRange): Boolean = (other.first public interface Series : Buffer { public val origin: Buffer + /** * Absolute position of start of this [Series] in [SeriesAlgebra] */ @@ -114,7 +115,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( public operator fun Buffer.get(label: L): T? { val index = labels.indexOf(label) if (index == -1) return null - return getAbsolute(index + offset.toInt()) + return getAbsolute(index + offset) } /** From 6bf8d9d325d6a04e74c2b776cc8f7025729a5f94 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Sep 2022 13:08:49 +0300 Subject: [PATCH 08/72] Naming refactoring --- .../commons/transform/Transformations.kt | 53 +++--- .../space/kscience/kmath/complex/Complex.kt | 1 - .../kmath/operations/bufferOperation.kt | 16 +- .../kscience/kmath/structures/DoubleBuffer.kt | 20 ++- .../space/kscience/kmath/misc/JBigTest.kt | 20 +++ .../kscience/kmath/streaming/BufferFlow.kt | 7 +- .../kmath/tensors/core/DoubleTensor.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 14 +- .../kscience/kmath/trajectory/DubinsPath.kt | 163 +++++++++++------- .../kscience/kmath/trajectory/Trajectory.kt | 12 +- .../space/kscience/kmath/trajectory/Math.kt | 6 +- .../kmath/trajectory/dubins/DubinsTests.kt | 10 +- .../kmath/trajectory/segments/ArcTests.kt | 4 +- .../kmath/trajectory/segments/LineTests.kt | 12 +- 14 files changed, 202 insertions(+), 138 deletions(-) create mode 100644 kmath-core/src/jvmTest/kotlin/space/kscience/kmath/misc/JBigTest.kt 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 2243dc5d9..a77da2d2f 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 @@ -10,28 +10,18 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import org.apache.commons.math3.transform.* import space.kscience.kmath.complex.Complex -import space.kscience.kmath.operations.SuspendBufferTransform +import space.kscience.kmath.operations.BufferTransform import space.kscience.kmath.streaming.chunked import space.kscience.kmath.streaming.spread -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.asBuffer - +import space.kscience.kmath.structures.* /** - * Streaming and buffer transformations + * Streaming and buffer transformations with Commons-math algorithms */ public object Transformations { - private fun Buffer.toArray(): Array = + private fun Buffer.toCmComplexArray(): Array = Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) } - private fun Buffer.asArray() = if (this is DoubleBuffer) { - array - } else { - DoubleArray(size) { i -> get(i) } - } - /** * Create a virtual buffer on top of array */ @@ -43,70 +33,67 @@ public object Transformations { public fun fourier( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD, - ): SuspendBufferTransform = { - FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer() + ): BufferTransform = BufferTransform { + FastFourierTransformer(normalization).transform(it.toCmComplexArray(), direction).asBuffer() } public fun realFourier( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD, - ): SuspendBufferTransform = { - FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer() + ): BufferTransform = BufferTransform { + FastFourierTransformer(normalization).transform(it.toDoubleArray(), direction).asBuffer() } public fun sine( normalization: DstNormalization = DstNormalization.STANDARD_DST_I, direction: TransformType = TransformType.FORWARD, - ): SuspendBufferTransform = { - FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer() + ): BufferTransform = DoubleBufferTransform { + FastSineTransformer(normalization).transform(it.array, direction).asBuffer() } public fun cosine( normalization: DctNormalization = DctNormalization.STANDARD_DCT_I, direction: TransformType = TransformType.FORWARD, - ): SuspendBufferTransform = { - FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer() + ): BufferTransform = BufferTransform { + FastCosineTransformer(normalization).transform(it.toDoubleArray(), direction).asBuffer() } public fun hadamard( direction: TransformType = TransformType.FORWARD, - ): SuspendBufferTransform = { - FastHadamardTransformer().transform(it.asArray(), direction).asBuffer() + ): BufferTransform = DoubleBufferTransform { + FastHadamardTransformer().transform(it.array, direction).asBuffer() } } /** * Process given [Flow] with commons-math fft transformation */ -@FlowPreview -public fun Flow>.FFT( +public fun Flow>.fft( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD, ): Flow> { val transform = Transformations.fourier(normalization, direction) - return map { transform(it) } + return map(transform::transform) } -@FlowPreview @JvmName("realFFT") -public fun Flow>.FFT( +public fun Flow>.fft( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD, ): Flow> { val transform = Transformations.realFourier(normalization, direction) - return map(transform) + return map(transform::transform) } /** * Process a continuous flow of real numbers in FFT splitting it in chunks of [bufferSize]. */ -@FlowPreview @JvmName("realFFT") -public fun Flow.FFT( +public fun Flow.fft( bufferSize: Int = Int.MAX_VALUE, normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD, -): Flow = chunked(bufferSize).FFT(normalization, direction).spread() +): Flow = chunked(bufferSize).fft(normalization, direction).spread() /** * Map a complex flow into real flow by taking real part of each number 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 5804e47c1..7bf8af4e8 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 @@ -193,7 +193,6 @@ public object ComplexField : * @property re The real part. * @property im The imaginary part. */ -@OptIn(UnstableKMathAPI::class) public data class Complex(val re: Double, val im: Double) { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number) : this(re.toDouble(), 0.0) 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 3d25d8750..0a5d6b964 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 @@ -9,14 +9,18 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.* /** - * Typealias for buffer transformations. + * Type alias for buffer transformations. */ -public typealias BufferTransform = (Buffer) -> Buffer +public fun interface BufferTransform { + public fun transform(arg: Buffer): Buffer +} -/** - * Typealias for buffer transformations with suspend function. - */ -public typealias SuspendBufferTransform = suspend (Buffer) -> Buffer +///** +// * Type alias for buffer transformations with suspend function. +// */ +//public fun interface SuspendBufferTransform{ +// public suspend fun transform(arg: Buffer): Buffer +//} /** 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 4dd9003f3..5d80f2b1f 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 @@ -5,6 +5,7 @@ package space.kscience.kmath.structures +import space.kscience.kmath.operations.BufferTransform import kotlin.jvm.JvmInline /** @@ -28,7 +29,7 @@ public value class DoubleBuffer(public val array: DoubleArray) : MutableBuffer Double): DoubleBuffer = DoubleBuffer(DoubleArray(size) { init(it) }) +public inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = + DoubleBuffer(DoubleArray(size) { init(it) }) /** * Returns a new [DoubleBuffer] of given elements. @@ -51,10 +53,15 @@ public fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(dou * Returns a new [DoubleArray] containing all the elements of this [Buffer]. */ public fun Buffer.toDoubleArray(): DoubleArray = when (this) { - is DoubleBuffer -> array.copyOf() + is DoubleBuffer -> array else -> DoubleArray(size, ::get) } +public fun Buffer.toDoubleBuffer(): DoubleBuffer = when (this) { + is DoubleBuffer -> this + else -> DoubleArray(size, ::get).asBuffer() +} + /** * Returns [DoubleBuffer] over this array. * @@ -62,3 +69,10 @@ public fun Buffer.toDoubleArray(): DoubleArray = when (this) { * @return the new buffer. */ public fun DoubleArray.asBuffer(): DoubleBuffer = DoubleBuffer(this) + + +public fun interface DoubleBufferTransform : BufferTransform { + public fun transform(arg: DoubleBuffer): DoubleBuffer + + override fun transform(arg: Buffer): DoubleBuffer = arg.toDoubleBuffer() +} diff --git a/kmath-core/src/jvmTest/kotlin/space/kscience/kmath/misc/JBigTest.kt b/kmath-core/src/jvmTest/kotlin/space/kscience/kmath/misc/JBigTest.kt new file mode 100644 index 000000000..f7f8027e6 --- /dev/null +++ b/kmath-core/src/jvmTest/kotlin/space/kscience/kmath/misc/JBigTest.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.misc + +import org.junit.jupiter.api.Test +import space.kscience.kmath.operations.JBigDecimalField +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals + +class JBigTest { + + @Test + fun testExact() = with(JBigDecimalField) { + assertNotEquals(0.3, 0.1 + 0.2) + assertEquals(one * 0.3, one * 0.1 + one * 0.2) + } +} \ No newline at end of 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 00c874751..8aa5a937c 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 @@ -5,8 +5,10 @@ package space.kscience.kmath.streaming -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.flatMapConcat +import kotlinx.coroutines.flow.flow import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -20,7 +22,6 @@ public fun Buffer.asFlow(): Flow = iterator().asFlow() /** * Flat map a [Flow] of [Buffer] into continuous [Flow] of elements */ -@FlowPreview public fun Flow>.spread(): Flow = flatMapConcat { it.asFlow() } /** 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 e9589eb0a..d3308a69f 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 @@ -28,7 +28,7 @@ public class OffsetDoubleBuffer( override fun get(index: Int): Double = source[index + offset] /** - * Copy only a part of buffer that belongs to this tensor + * Copy only a part of buffer that belongs to this [OffsetDoubleBuffer] */ override fun copy(): DoubleBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() 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 f563d00ae..67248890c 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 @@ -59,20 +59,16 @@ public open class DoubleTensorAlgebra : } } - public inline fun Tensor.mapIndexedInPlace(operation: (IntArray, Double) -> Double) { - indices.forEach { set(it, operation(it, get(it))) } + public inline fun Tensor.mapIndexedInPlace(operation: DoubleField.(IntArray, Double) -> Double) { + indices.forEach { set(it, DoubleField.operation(it, get(it))) } } @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: DoubleField.(index: IntArray, Double) -> Double): DoubleTensor { - val tensor = this.asDoubleTensor() - //TODO remove additional copy - val buffer = DoubleBuffer(tensor.source.size) { - DoubleField.transform(tensor.indices.index(it), tensor.source[it]) - } - return DoubleTensor(tensor.shape, buffer) + return copyToTensor().apply { mapIndexedInPlace(transform) } } + @Suppress("OVERRIDE_BY_INLINE") final override inline fun zip( left: StructureND, @@ -92,7 +88,7 @@ public open class DoubleTensorAlgebra : public inline fun StructureND.reduceElements(transform: (DoubleBuffer) -> Double): Double = transform(asDoubleTensor().source.copy()) - //TODO do we need protective copy? + //TODO Add read-only DoubleBuffer wrapper. To avoid protective copy override fun StructureND.valueOrNull(): Double? { val dt = asDoubleTensor() 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 index e90e3de41..6a340f6b9 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -23,64 +23,65 @@ internal fun Pose2D.getTangentCircles(radius: Double): Pair 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 leftOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory = outerTangent(a, b, CircleTrajectory.Direction.LEFT) -internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, - ArcSegment.Direction.RIGHT +internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory = outerTangent(a, b, + CircleTrajectory.Direction.RIGHT ) -private fun outerTangent(a: Circle2D, b: Circle2D, side: ArcSegment.Direction): StraightSegment = with(Euclidean2DSpace){ - val centers = StraightSegment(a.center, b.center) +private fun outerTangent(a: Circle2D, b: Circle2D, side: CircleTrajectory.Direction): StraightTrajectory = with(Euclidean2DSpace){ + val centers = StraightTrajectory(a.center, b.center) val p1 = when (side) { - ArcSegment.Direction.LEFT -> vector( + CircleTrajectory.Direction.LEFT -> vector( a.center.x - a.radius * cos(centers.theta), a.center.y + a.radius * sin(centers.theta) ) - ArcSegment.Direction.RIGHT -> vector( + CircleTrajectory.Direction.RIGHT -> vector( a.center.x + a.radius * cos(centers.theta), a.center.y - a.radius * sin(centers.theta) ) } - return StraightSegment( + return StraightTrajectory( 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 leftInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory? = + innerTangent(base, direction, CircleTrajectory.Direction.LEFT) -internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = - innerTangent(base, direction, ArcSegment.Direction.RIGHT) +internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory? = + innerTangent(base, direction, CircleTrajectory.Direction.RIGHT) -private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.Direction): StraightSegment? = with(Euclidean2DSpace){ - val centers = StraightSegment(base.center, direction.center) +private fun innerTangent(base: Circle2D, direction: Circle2D, side: CircleTrajectory.Direction): StraightTrajectory? = with(Euclidean2DSpace){ + val centers = StraightTrajectory(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) + CircleTrajectory.Direction.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + CircleTrajectory.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) + return StraightTrajectory(p1, p2) } internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) +@Suppress("DuplicatedCode") public class DubinsPath( - public val a: ArcSegment, + public val a: CircleTrajectory, public val b: Trajectory, - public val c: ArcSegment, + public val c: CircleTrajectory, ) : 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', + if (b is CircleTrajectory) b.direction.name[0] else 'S', c.direction.name[0] ).toCharArray().concatToString() ) @@ -106,56 +107,98 @@ public class DubinsPath( 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){ + 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) + val centers = StraightTrajectory(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) + val firstVariant = run { + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.RIGHT) + val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.LEFT) + val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.RIGHT) + DubinsPath(a1, a2, a3) + } + + val secondVariant = run { + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.RIGHT) + val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.LEFT) + val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.RIGHT) + DubinsPath(a1, a2, a3) + } + + return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } - public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath?= with(Euclidean2DSpace) { + 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) + val centers = StraightTrajectory(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) + val firstVariant = run { + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.LEFT) + val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.RIGHT) + val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.LEFT) + DubinsPath(a1, a2, a3) + } + + val secondVariant = run{ + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.LEFT) + val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.RIGHT) + val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.LEFT) + DubinsPath(a1, a2, a3) + } + + return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } 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) + val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.RIGHT) + val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.RIGHT) return DubinsPath(a1, s, a3) } @@ -163,8 +206,8 @@ public class 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) + val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.LEFT) + val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -174,8 +217,8 @@ public class DubinsPath( 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) + val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.RIGHT) + val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -185,8 +228,8 @@ public class DubinsPath( 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) + val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.LEFT) + val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.RIGHT) return DubinsPath(a1, s, a3) } } 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 index 03b0fcec9..1085f7847 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt @@ -19,7 +19,7 @@ public sealed interface Trajectory { /** * Straight path segment. The order of start and end defines the direction */ -public data class StraightSegment( +public data class StraightTrajectory( internal val start: DoubleVector2D, internal val end: DoubleVector2D, ) : Trajectory { @@ -31,7 +31,7 @@ public data class StraightSegment( /** * An arc segment */ -public data class ArcSegment( +public data class CircleTrajectory( public val circle: Circle2D, public val start: Pose2D, public val end: Pose2D, @@ -68,7 +68,7 @@ public data class ArcSegment( } public companion object { - public fun of(center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, direction: Direction): ArcSegment { + public fun of(center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, direction: Direction): CircleTrajectory { fun calculatePose( vector: DoubleVector2D, theta: Double, @@ -81,11 +81,11 @@ public data class ArcSegment( } ) - val s1 = StraightSegment(center, start) - val s2 = StraightSegment(center, end) + val s1 = StraightTrajectory(center, start) + val s2 = StraightTrajectory(center, end) val pose1 = calculatePose(start, s1.theta, direction) val pose2 = calculatePose(end, s2.theta, direction) - return ArcSegment(Circle2D(center, s1.length), pose1, pose2) + return CircleTrajectory(Circle2D(center, s1.length), pose1, pose2) } } } 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 index 3b2535cee..64513f6e2 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt @@ -17,12 +17,12 @@ 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){ +fun StraightTrajectory.inverse() = StraightTrajectory(end, start) +fun StraightTrajectory.shift(shift: Int, width: Double): StraightTrajectory = with(Euclidean2DSpace){ val dX = width * sin(inverse().theta) val dY = width * sin(theta) - return StraightSegment( + return StraightTrajectory( 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 index 166567475..b545b7c94 100644 --- 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 @@ -16,7 +16,7 @@ class DubinsTests { @Test fun dubinsTest() = with(Euclidean2DSpace){ - val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) + val straight = StraightTrajectory(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) @@ -45,12 +45,12 @@ class DubinsTests { assertTrue(end.equalsFloat(path.c.end)) // Not working, theta double precision inaccuracy - if (path.b is ArcSegment) { - val b = path.b as ArcSegment + if (path.b is CircleTrajectory) { + val b = path.b as CircleTrajectory 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 + } else if (path.b is StraightTrajectory) { + val b = path.b as StraightTrajectory 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 index 86c79a5d6..17277c35e 100644 --- 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 @@ -8,7 +8,7 @@ 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.CircleTrajectory import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.test.Test import kotlin.test.assertEquals @@ -18,7 +18,7 @@ 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) + val arc = CircleTrajectory.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), CircleTrajectory.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/LineTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt index c5e88c1f1..4b54d775c 100644 --- 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.trajectory.StraightSegment +import space.kscience.kmath.trajectory.StraightTrajectory import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow import kotlin.math.sqrt @@ -17,7 +17,7 @@ class LineTests { @Test fun lineTest() = with(Euclidean2DSpace){ - val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) + val straight = StraightTrajectory(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()) } @@ -25,13 +25,13 @@ class LineTests { @Test fun lineAngleTest() = with(Euclidean2DSpace){ //val zero = Vector2D(0.0, 0.0) - val north = StraightSegment(Euclidean2DSpace.zero, vector(0.0, 2.0)) + val north = StraightTrajectory(Euclidean2DSpace.zero, vector(0.0, 2.0)) assertEquals(0.0, north.theta.radiansToDegrees()) - val east = StraightSegment(Euclidean2DSpace.zero, vector(2.0, 0.0)) + val east = StraightTrajectory(Euclidean2DSpace.zero, vector(2.0, 0.0)) assertEquals(90.0, east.theta.radiansToDegrees()) - val south = StraightSegment(Euclidean2DSpace.zero, vector(0.0, -2.0)) + val south = StraightTrajectory(Euclidean2DSpace.zero, vector(0.0, -2.0)) assertEquals(180.0, south.theta.radiansToDegrees()) - val west = StraightSegment(Euclidean2DSpace.zero, vector(-2.0, 0.0)) + val west = StraightTrajectory(Euclidean2DSpace.zero, vector(-2.0, 0.0)) assertEquals(270.0, west.theta.radiansToDegrees()) } } From d70389d2e622c93fa5ffb0f828428ae5261ab1f9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Sep 2022 16:47:38 +0300 Subject: [PATCH 09/72] Fix after series merge --- .../kotlin/space/kscience/kmath/fit/chiSquared.kt | 4 ++-- .../main/kotlin/space/kscience/kmath/fit/qowFit.kt | 4 ++-- .../kotlin/space/kscience/kmath/series/analyzeDif.kt | 5 +++-- .../kscience/kmath/structures/StreamDoubleFieldND.kt | 3 ++- .../kmath/commons/random/CMRandomGeneratorWrapper.kt | 3 +-- .../kmath/commons/optimization/OptimizeTest.kt | 2 +- .../kscience/kmath/expressions/specialExpressions.kt | 2 +- .../kotlin/space/kscience/kmath/nd/DoubleFieldND.kt | 8 ++++---- .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 2 +- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 6 +++--- .../kotlin/space/kscience/kmath/structures/Buffer.kt | 1 + .../space/kscience/kmath/streaming/RingBufferTest.kt | 2 +- .../kotlin/space/kscience/kmath/real/RealMatrix.kt | 4 ++-- .../kotlin/space/kscience/kmath/real/realND.kt | 4 ++-- .../kmath/integration/GaussIntegratorRuleFactory.kt | 4 ++-- .../kscience/kmath/integration/SplineIntegrator.kt | 6 +----- .../space/kscience/kmath/geometry/Vector2DTest.kt | 2 +- .../space/kscience/kmath/geometry/Vector3DTest.kt | 2 +- .../kmath/histogram/UniformHistogram1DTest.kt | 8 ++++---- .../space/kscience/kmath/jupyter/KMathJupyter.kt | 4 +++- .../kscience/kmath/distributions/Distribution.kt | 2 +- .../kmath/distributions/UniformDistribution.kt | 5 ++--- .../kmath/samplers/AhrensDieterExponentialSampler.kt | 1 + .../AhrensDieterMarsagliaTsangGammaSampler.kt | 2 ++ .../kmath/samplers/AliasMethodDiscreteSampler.kt | 1 + .../kmath/samplers/KempSmallMeanPoissonSampler.kt | 1 + .../kmath/samplers/NormalizedGaussianSampler.kt | 1 + .../space/kscience/kmath/samplers/PoissonSampler.kt | 1 + .../kotlin/space/kscience/kmath/samplers/Sampler.kt | 1 + .../space/kscience/kmath/samplers/SamplerAlgebra.kt | 1 + .../space/kscience/kmath/series/SeriesAlgebra.kt | 8 ++++---- .../kotlin/space/kscience/kmath/stat/Median.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Rank.kt | 2 +- .../space/kscience/kmath/stat/StatisticalAlgebra.kt | 11 +++++------ .../kotlin/space/kscience/kmath/stat/SamplerTest.kt | 2 -- .../kscience/kmath/tensors/core/internal/utils.kt | 2 +- 36 files changed, 62 insertions(+), 57 deletions(-) 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 80baf1795..febf55283 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -12,6 +12,8 @@ import space.kscience.kmath.commons.optimization.CMOptimizer import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.operations.asIterable +import space.kscience.kmath.operations.toList import space.kscience.kmath.optimization.FunctionOptimizationTarget import space.kscience.kmath.optimization.optimizeWith import space.kscience.kmath.optimization.resultPoint @@ -20,8 +22,6 @@ import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step -import space.kscience.kmath.structures.asIterable -import space.kscience.kmath.structures.toList import space.kscience.plotly.* import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.TraceValues 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 d6676b9ca..c7eefa6b9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -13,6 +13,8 @@ import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.binding import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.operations.asIterable +import space.kscience.kmath.operations.toList import space.kscience.kmath.optimization.QowOptimizer import space.kscience.kmath.optimization.chiSquaredOrNull import space.kscience.kmath.optimization.fitWith @@ -20,8 +22,6 @@ import space.kscience.kmath.optimization.resultPoint import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.map import space.kscience.kmath.real.step -import space.kscience.kmath.structures.asIterable -import space.kscience.kmath.structures.toList import space.kscience.plotly.* import space.kscience.plotly.models.ScatterMode import kotlin.math.abs diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index b9c3141dd..308345ded 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -3,12 +3,13 @@ package space.kscience.kmath.series import kotlinx.html.FlowContent import kotlinx.html.h1 +import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.operations.toList import space.kscience.kmath.stat.ksComparisonStatistic import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.slice -import space.kscience.kmath.structures.toList import space.kscience.plotly.* import kotlin.math.PI @@ -33,7 +34,7 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s2 = s1.slice(20U..50U).moveTo(40) val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 - val s4 = ln(s3) + val s4 = DoubleBufferOps.ln(s3) val kmTest = ksComparisonStatistic(s1, s2) 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 b047a2aff..1061112eb 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -37,7 +37,8 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND this.buffer as DoubleBuffer + + this is BufferND && indices == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } 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 62967eae5..32962659f 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 @@ -6,11 +6,10 @@ package space.kscience.kmath.commons.random import kotlinx.coroutines.runBlocking -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler -import space.kscience.kmath.samplers.next +import space.kscience.kmath.stat.next public class CMRandomGeneratorWrapper( 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 53d86c6b7..f6819a27f 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 @@ -13,11 +13,11 @@ import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.y import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.operations.map import space.kscience.kmath.optimization.* import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.structures.map import kotlin.math.pow import kotlin.test.Test 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 f56b1f6d6..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 @@ -6,8 +6,8 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.indices import kotlin.jvm.JvmName 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 f7b81f46f..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 @@ -15,7 +15,7 @@ import kotlin.math.pow import kotlin.math.pow as kpow public class DoubleBufferND( - indexes: ShapeIndices, + indexes: ShapeIndexer, override val buffer: DoubleBuffer, ) : MutableBufferND(indexes, buffer) @@ -35,7 +35,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D arg: DoubleBufferND, transform: (Double) -> Double, ): DoubleBufferND { - val indexes = arg.shapeIndices + val indexes = arg.indices val array = arg.buffer.array return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { transform(array[it]) }) } @@ -45,8 +45,8 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D r: DoubleBufferND, block: (l: Double, r: Double) -> Double, ): DoubleBufferND { - require(l.shapeIndices == r.shapeIndices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } - val indexes = l.shapeIndices + require(l.indices == r.indices) { "Zip requires the same shapes, but found ${l.shape} on the left and ${r.shape} on the right" } + val indexes = l.indices val lArray = l.buffer.array val rArray = r.buffer.array return DoubleBufferND(indexes, DoubleBuffer(indexes.linearSize) { block(lArray[it], rArray[it]) }) 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 47feefd43..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 @@ -6,10 +6,10 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.asMutableBuffer -import space.kscience.kmath.structures.asSequence import kotlin.jvm.JvmInline /** 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 7d417c4ed..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 @@ -54,7 +54,7 @@ public interface StructureND : Featured, WithShape { * @return the lazy sequence of pairs of indices to values. */ @PerformancePitfall - public fun elements(): Sequence> = shapeIndices.asSequence().map { it to get(it) } + public fun elements(): Sequence> = indices.asSequence().map { it to get(it) } /** * Feature is some additional structure information that allows to access it special properties or hints. @@ -71,7 +71,7 @@ public interface StructureND : Featured, WithShape { if (st1 === st2) return true // fast comparison of buffers if possible - if (st1 is BufferND && st2 is BufferND && st1.shapeIndices == st2.shapeIndices) + if (st1 is BufferND && st2 is BufferND && st1.indices == st2.indices) return Buffer.contentEquals(st1.buffer, st2.buffer) //element by element comparison if it could not be avoided @@ -87,7 +87,7 @@ public interface StructureND : Featured, WithShape { if (st1 === st2) return true // fast comparison of buffers if possible - if (st1 is BufferND && st2 is BufferND && st1.shapeIndices == st2.shapeIndices) + if (st1 is BufferND && st2 is BufferND && st1.indices == st2.indices) return Buffer.contentEquals(st1.buffer, st2.buffer) //element by element comparison if it could not be avoided 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 75b0f54f0..cef8d1d4d 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.operations.WithSize +import space.kscience.kmath.operations.asSequence import kotlin.jvm.JvmInline import kotlin.reflect.KClass 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 dea694016..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 @@ -7,7 +7,7 @@ package space.kscience.kmath.streaming import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking -import space.kscience.kmath.structures.asSequence +import space.kscience.kmath.operations.asSequence import kotlin.test.Test import kotlin.test.assertEquals 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 1b6490862..cfa59bf32 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 @@ -13,9 +13,9 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.asIterable import kotlin.math.pow /* @@ -131,7 +131,7 @@ public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix = extractColumns(columnIndex..columnIndex) public fun RealMatrix.sumByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> - columns[j].asIterable().sum() + columns[j].sum() } public fun RealMatrix.minByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> 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 e9f0d3063..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 @@ -13,8 +13,8 @@ import space.kscience.kmath.structures.DoubleBuffer * Map one [BufferND] using function without indices. */ public inline fun BufferND.mapInline(crossinline transform: DoubleField.(Double) -> Double): BufferND { - val array = DoubleArray(shapeIndices.linearSize) { offset -> DoubleField.transform(buffer[offset]) } - return BufferND(shapeIndices, DoubleBuffer(array)) + val array = DoubleArray(indices.linearSize) { offset -> DoubleField.transform(buffer[offset]) } + return BufferND(indices, DoubleBuffer(array)) } /** 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 57d77ab47..3845bd2a7 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 @@ -5,10 +5,10 @@ package space.kscience.kmath.integration +import space.kscience.kmath.operations.map import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.structures.map import kotlin.jvm.Synchronized import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal @@ -30,7 +30,7 @@ public fun GaussIntegratorRuleFactory.build( numPoints: Int, range: ClosedRange, ): Pair, Buffer> { - val normalized = build(numPoints) + val normalized: Pair, Buffer> = build(numPoints) val length = range.endInclusive - range.start val points = normalized.first.map(::DoubleBuffer) { 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 6189d17cd..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 @@ -12,14 +12,10 @@ import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.sum +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.MutableBufferFactory -import space.kscience.kmath.structures.map /** * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact 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 6ad323f26..0db06f4c8 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.structures.toList +import space.kscience.kmath.operations.toList import kotlin.test.Test import kotlin.test.assertEquals 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 6716bf940..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 @@ -5,7 +5,7 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.structures.toList +import space.kscience.kmath.operations.toList import kotlin.test.Test import kotlin.test.assertEquals 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 fd107f5e8..c4554b575 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 @@ -10,7 +10,7 @@ import kotlinx.coroutines.test.runTest import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.stat.nextBuffer import kotlin.native.concurrent.ThreadLocal import kotlin.test.Test @@ -36,7 +36,7 @@ internal class UniformHistogram1DTest { @Test fun rebinDown() = runTest { val h1 = Histogram.uniform1D(DoubleField, 0.01).produce(generator.nextDoubleBuffer(10000)) - val h2 = Histogram.uniform1D(DoubleField,0.03).produceFrom(h1) + val h2 = Histogram.uniform1D(DoubleField, 0.03).produceFrom(h1) assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt()) } @@ -44,13 +44,13 @@ internal class UniformHistogram1DTest { @Test fun rebinUp() = runTest { val h1 = Histogram.uniform1D(DoubleField, 0.03).produce(generator.nextDoubleBuffer(10000)) - val h2 = Histogram.uniform1D(DoubleField,0.01).produceFrom(h1) + val h2 = Histogram.uniform1D(DoubleField, 0.01).produceFrom(h1) assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt()) } @ThreadLocal - companion object{ + companion object { private val generator = RandomGenerator.default(123) } } \ No newline at end of file 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 18630ee14..1fe9fe92f 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 @@ -21,9 +21,9 @@ import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.operations.asSequence import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asSequence /** * A function for conversion of number to MST for pretty print @@ -47,11 +47,13 @@ internal class KMathJupyter : JupyterIntegration() { syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) +s.toString() } + is MST -> { val s = StringBuilder() syntaxRender.renderPart(mathRender.render(it), s) +s.toString() } + else -> { +"" +it.toString() 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 aca224375..806da5560 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.random.RandomGenerator -import space.kscience.kmath.samplers.Sampler +import space.kscience.kmath.stat.Sampler /** * A distribution of typed objects. diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt index fa51bb521..953be06fd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/UniformDistribution.kt @@ -3,12 +3,11 @@ * 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.stat +package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain -import space.kscience.kmath.distributions.Distribution -import space.kscience.kmath.distributions.Distribution1D +import space.kscience.kmath.random.RandomGenerator public class UniformDistribution(public val range: ClosedFloatingPointRange) : Distribution1D { private val length: Double = range.endInclusive - range.start 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 67d2c8003..e5a48d4d8 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.ln import kotlin.math.pow 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 30fce19e9..d301ff637 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 @@ -8,6 +8,8 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.random.chain +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.next import kotlin.math.* /** 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 dc88d866f..2ec40c347 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 @@ -8,6 +8,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.random.chain +import space.kscience.kmath.stat.Sampler import kotlin.math.ceil import kotlin.math.max import kotlin.math.min 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 be378c2fc..6d2899314 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.IntBuffer import kotlin.math.exp 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 ea121bfa6..291d0bffe 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.Sampler public interface BlockingDoubleSampler : Sampler { override fun sample(generator: RandomGenerator): BlockingDoubleChain 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 5dcf4e3e2..454691e05 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 @@ -8,6 +8,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.IntBuffer import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt index 66ade8119..52e400bf1 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/Sampler.kt @@ -9,6 +9,7 @@ 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.random.RandomGenerator import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt index 748da727b..44b87a431 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/SamplerAlgebra.kt @@ -13,6 +13,7 @@ import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.Sampler /** * Implements [Sampler] by sampling only certain [value]. diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 79da3d98d..96ad4daf7 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -97,7 +97,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( * Build a new series */ public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Series { - return bufferFactory(size) { + return elementAlgebra.bufferFactory(size) { val index = it + fromIndex elementAlgebra.block(labelResolver(index)) }.moveTo(fromIndex) @@ -122,7 +122,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( * Map a series to another series of the same size */ public inline fun Buffer.map(crossinline transform: A.(T) -> T): Series { - val buf = bufferFactory(size) { + val buf = elementAlgebra.bufferFactory(size) { elementAlgebra.transform(getAbsolute(it)) } return buf.moveTo(indices.first) @@ -133,7 +133,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( */ public inline fun Buffer.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Series { val labels = labels - val buf = bufferFactory(size) { + val buf = elementAlgebra.bufferFactory(size) { elementAlgebra.transform(getAbsolute(it), labels[it]) } return buf.moveTo(indices.first) @@ -161,7 +161,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( crossinline operation: A.(left: T, right: T) -> T, ): Series { val newRange = indices.intersect(other.indices) - return bufferFactory(newRange.size) { + return elementAlgebra.bufferFactory(newRange.size) { elementAlgebra.operation( getAbsolute(it), other.getAbsolute(it) 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 cc7d488dc..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 @@ -5,8 +5,8 @@ package space.kscience.kmath.stat +import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asSequence /** * Non-composable median diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt index 5a5b99177..5a873b466 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Rank.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.stat +import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asIterable /** * Rank statistics diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt index fcda58268..f36826c28 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/StatisticalAlgebra.kt @@ -1,16 +1,15 @@ package space.kscience.kmath.stat import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.misc.sorted import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.asIterable -import space.kscience.kmath.structures.sorted +import space.kscience.kmath.structures.MutableBufferFactory public interface StatisticalAlgebra, out BA : BufferAlgebra> : Algebra> { public val bufferAlgebra: BA public val elementAlgebra: A get() = bufferAlgebra.elementAlgebra - public val bufferFactory: BufferFactory get() = bufferAlgebra.bufferFactory + override val bufferFactory: MutableBufferFactory> get() = bufferAlgebra.bufferFactory } /** @@ -41,8 +40,8 @@ public fun , A, BA : BufferAlgebra> StatisticalAlgebra Date: Tue, 27 Sep 2022 16:57:06 +0300 Subject: [PATCH 10/72] Change the default strides and unify strides processing --- .../space/kscience/kmath/series/analyzeDif.kt | 5 +- .../kmath/structures/StreamDoubleFieldND.kt | 2 +- .../structures/StructureReadBenchmark.kt | 4 +- .../space/kscience/kmath/nd/BufferND.kt | 4 +- .../kotlin/space/kscience/kmath/nd/Shape.kt | 2 +- .../space/kscience/kmath/nd/ShapeIndices.kt | 73 +++++++++++++--- .../space/kscience/kmath/nd/Structure2D.kt | 9 +- .../space/kscience/kmath/nd/StructureND.kt | 8 +- .../kmath/structures/BufferAccessor2D.kt | 4 +- .../kscience/kmath/structures/BufferView.kt | 33 ++++---- .../kmath/structures/bufferPrimitiveAccess.kt | 4 +- .../space/kscience/kmath/nd/StridesTest.kt | 38 +++++++++ .../kmath/structures/BufferExpandedTest.kt | 2 +- .../kmath/structures/LazyStructureND.kt | 4 +- .../kscience/kmath/histogram/HistogramND.kt | 4 +- .../histogram/MultivariateHistogramTest.kt | 4 +- .../kmath/multik/MultikTensorAlgebra.kt | 2 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 4 +- .../kscience/kmath/series/SeriesAlgebra.kt | 6 +- .../tensorflow/DoubleTensorFlowAlgebra.kt | 4 +- .../kmath/tensors/core/BufferedTensor.kt | 5 +- .../kmath/tensors/core/DoubleTensor.kt | 83 +++++++++++++++++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 5 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 2 +- .../tensors/core/TensorLinearStructure.kt | 74 ----------------- .../core/internal/doubleTensorHelpers.kt | 13 +-- .../tensors/core/internal/intTensorHelpers.kt | 19 ++--- .../kmath/tensors/core/internal/utils.kt | 8 +- .../kmath/tensors/core/tensorTransform.kt | 9 +- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 8 +- .../kmath/viktor/ViktorStructureND.kt | 4 +- 32 files changed, 268 insertions(+), 180 deletions(-) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index 308345ded..c1b0c056e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -7,6 +7,7 @@ import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.toList +import space.kscience.kmath.stat.KMComparisonResult import space.kscience.kmath.stat.ksComparisonStatistic import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.slice @@ -31,12 +32,12 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 } - val s2 = s1.slice(20U..50U).moveTo(40) + val s2 = s1.slice(20..50).moveTo(40) val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s4 = DoubleBufferOps.ln(s3) - val kmTest = ksComparisonStatistic(s1, s2) + val kmTest: KMComparisonResult = ksComparisonStatistic(s1, s2) Plotly.page { h1 { +"This is my plot" } 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 1061112eb..f97e98973 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -21,7 +21,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND>, ExtendedField> { - private val strides = DefaultStrides(shape) + private val strides = ColumnStrides(shape) override val elementAlgebra: DoubleField get() = DoubleField override val zero: BufferND by lazy { structureND(shape) { zero } } override val one: BufferND by lazy { structureND(shape) { one } } 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 a64ac7280..ae7693f03 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.nd.BufferND -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import kotlin.system.measureTimeMillis @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") @@ -14,7 +14,7 @@ fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } val buffer = DoubleBuffer(array) - val strides = DefaultStrides(intArrayOf(n, n)) + val strides = ColumnStrides(intArrayOf(n, n)) val structure = BufferND(strides, buffer) measureTimeMillis { 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 1eb08fa8c..7efc785fb 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 @@ -38,7 +38,7 @@ public inline fun StructureND.mapToBuffer( ): BufferND = if (this is BufferND) BufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) else { - val strides = DefaultStrides(shape) + val strides = ColumnStrides(shape) BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } @@ -75,7 +75,7 @@ public inline fun MutableStructureND.mapToMutableBuffer( return if (this is MutableBufferND) MutableBufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) else { - val strides = DefaultStrides(shape) + val strides = ColumnStrides(shape) MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } } \ No newline at end of file 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 index c5d04c9de..fc0b4b6ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt @@ -24,7 +24,7 @@ public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(sha public interface WithShape { public val shape: Shape - public val indices: ShapeIndexer get() = DefaultStrides(shape) + public val indices: ShapeIndexer get() = ColumnStrides(shape) } internal fun requireIndexInShape(index: IntArray, shape: Shape) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index 2dce407ca..4b31e3fc5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import kotlin.math.max import kotlin.native.concurrent.ThreadLocal /** @@ -61,12 +62,16 @@ public abstract class Strides : ShapeIndexer { * Iterate over ND indices in a natural order */ public override fun asSequence(): Sequence = (0 until linearSize).asSequence().map(::index) + + public companion object{ + public fun linearSizeOf(shape: IntArray): Int = shape.reduce(Int::times) + } } /** - * Simple implementation of [Strides]. + * Column-first [Strides]. Columns are represented as continuous arrays */ -public class DefaultStrides(override val shape: IntArray) : Strides() { +public class ColumnStrides(override val shape: IntArray) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -100,22 +105,64 @@ public class DefaultStrides(override val shape: IntArray) : Strides() { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is DefaultStrides) return false - if (!shape.contentEquals(other.shape)) return false - return true + if (other !is ColumnStrides) return false + return shape.contentEquals(other.shape) } override fun hashCode(): Int = shape.contentHashCode() - public companion object { - /** - * Cached builder for default strides - */ - @Deprecated("Replace by Strides(shape)") - public operator fun invoke(shape: IntArray): Strides = - defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } + public companion object +} + +/** + * This [Strides] implementation follows the last dimension first convention + * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html + * + * @param shape the shape of the tensor. + */ +public class RowStrides(override val shape: IntArray) : Strides() { + + override val strides: IntArray by lazy { + val nDim = shape.size + val res = IntArray(nDim) + if (nDim == 0) return@lazy res + + var current = nDim - 1 + res[current] = 1 + + while (current > 0) { + res[current - 1] = max(1, shape[current]) * res[current] + current-- + } + res } + + override fun index(offset: Int): IntArray { + val res = IntArray(shape.size) + var current = offset + var strideIndex = 0 + + while (strideIndex < shape.size) { + res[strideIndex] = (current / strides[strideIndex]) + current %= strides[strideIndex] + strideIndex++ + } + return res + } + + override val linearSize: Int get() = linearSizeOf(shape) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is RowStrides) return false + return shape.contentEquals(other.shape) + } + + override fun hashCode(): Int = shape.contentHashCode() + + public companion object + } @ThreadLocal @@ -124,4 +171,4 @@ 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 +public fun Strides(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of 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 d8fd2031c..2822a74d4 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableListBuffer import space.kscience.kmath.structures.VirtualBuffer import kotlin.jvm.JvmInline @@ -84,15 +85,15 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * The buffer of rows of this structure. It gets elements from the structure dynamically. */ @PerformancePitfall - override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableListBuffer(colNum) { j -> get(i, j) }) } + override val rows: List> + get() = List(rowNum) { i -> MutableListBuffer(colNum) { j -> get(i, j) } } /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ @PerformancePitfall - override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableListBuffer(rowNum) { i -> get(i, j) }) } + override val columns: List> + get() = List(colNum) { j -> MutableListBuffer(rowNum) { i -> get(i, j) } } } /** 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 b2da083bb..4e1cc1ff4 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 @@ -148,25 +148,25 @@ public interface StructureND : Featured, WithShape { shape: IntArray, bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, - ): BufferND = buffered(DefaultStrides(shape), bufferFactory, initializer) + ): BufferND = buffered(ColumnStrides(shape), bufferFactory, initializer) public inline fun auto( shape: IntArray, crossinline initializer: (IntArray) -> T, - ): BufferND = auto(DefaultStrides(shape), initializer) + ): BufferND = auto(ColumnStrides(shape), initializer) @JvmName("autoVarArg") public inline fun auto( vararg shape: Int, crossinline initializer: (IntArray) -> T, ): BufferND = - auto(DefaultStrides(shape), initializer) + auto(ColumnStrides(shape), initializer) public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): BufferND = auto(type, DefaultStrides(shape), initializer) + ): BufferND = auto(type, ColumnStrides(shape), 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 07355d396..f61a0a623 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.structures -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D @@ -31,7 +31,7 @@ internal class BufferAccessor2D( //TODO optimize wrapper fun MutableBuffer.collect(): Structure2D = StructureND.buffered( - DefaultStrides(intArrayOf(rowNum, colNum)), + ColumnStrides(intArrayOf(rowNum, colNum)), factory ) { (i, j) -> get(i, j) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt index 8dc0d63ef..e8ab4f0ba 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -15,6 +15,9 @@ public interface BufferView : Buffer { */ @UnstableKMathAPI public fun originIndex(index: Int): Int + + @OptIn(UnstableKMathAPI::class) + override fun get(index: Int): T = origin[originIndex(index)] } /** @@ -22,40 +25,40 @@ public interface BufferView : Buffer { */ public class BufferSlice( override val origin: Buffer, - public val offset: UInt = 0U, + public val offset: Int = 0, override val size: Int, ) : BufferView { init { require(size > 0) { "Size must be positive" } - require(offset + size.toUInt() <= origin.size.toUInt()) { - "End of buffer ${offset + size.toUInt()} is beyond the end of origin buffer size ${origin.size}" + require(offset + size <= origin.size) { + "End of buffer ${offset + size} is beyond the end of origin buffer size ${origin.size}" } } override fun get(index: Int): T = if (index >= size) { throw IndexOutOfBoundsException("$index is out of ${0 until size} rage") } else { - origin[index.toUInt() + offset] + origin[index + offset] } override fun iterator(): Iterator = - (offset until (offset + size.toUInt())).asSequence().map { origin[it] }.iterator() + (offset until (offset + size)).asSequence().map { origin[it] }.iterator() @UnstableKMathAPI - override fun originIndex(index: Int): Int = if (index >= size) -1 else index - offset.toInt() + override fun originIndex(index: Int): Int = if (index >= size) -1 else index - offset - override fun toString(): String = "$origin[$offset..${offset + size.toUInt()}" + override fun toString(): String = "$origin[$offset..${offset + size}" } /** - * An expanded buffer that could include the whole initial buffer ot its part and fills all space beyond it borders with [defaultValue]. + * An expanded buffer that could include the whole initial buffer or its part and fills all space beyond it borders with [defaultValue]. * * The [offset] parameter shows the shift of expanded buffer start relative to origin start and could be both positive and negative. */ public class BufferExpanded( override val origin: Buffer, - public val defaultValue: T, + private val defaultValue: T, public val offset: Int = 0, override val size: Int = origin.size, ) : BufferView { @@ -79,17 +82,17 @@ public class BufferExpanded( /** * Zero-copy select a slice inside the original buffer */ -public fun Buffer.slice(range: UIntRange): BufferView = if (this is BufferSlice) { +public fun Buffer.slice(range: IntRange): BufferView = if (this is BufferSlice) { BufferSlice( origin, this.offset + range.first, - (range.last - range.first).toInt() + 1 + (range.last - range.first) + 1 ) } else { BufferSlice( this, range.first, - (range.last - range.first).toInt() + 1 + (range.last - range.first) + 1 ) } @@ -103,7 +106,7 @@ public fun Buffer.expand( ): BufferView = if (range.first >= 0 && range.last < size) { BufferSlice( this, - range.first.toUInt(), + range.first, (range.last - range.first) + 1 ) } else { @@ -118,7 +121,7 @@ public fun Buffer.expand( /** * A [BufferView] that overrides indexing of the original buffer */ -public class PermutatedBuffer( +public class PermutedBuffer( override val origin: Buffer, private val permutations: IntArray, ) : BufferView { @@ -145,4 +148,4 @@ public class PermutatedBuffer( /** * Created a permuted view of given buffer using provided [indices] */ -public fun Buffer.permute(indices: IntArray): PermutatedBuffer = PermutatedBuffer(this, indices) \ No newline at end of file +public fun Buffer.permute(indices: IntArray): PermutedBuffer = PermutedBuffer(this, indices) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt index d361cb013..2f2cc80b3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferPrimitiveAccess.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI public fun Buffer.getDouble(index: Int): Double = if (this is BufferView) { val originIndex = originIndex(index) - if( originIndex>=0) { + if (originIndex >= 0) { origin.getDouble(originIndex) } else { get(index) @@ -26,7 +26,7 @@ public fun Buffer.getDouble(index: Int): Double = if (this is BufferView @UnstableKMathAPI public fun Buffer.getInt(index: Int): Int = if (this is BufferView) { val originIndex = originIndex(index) - if( originIndex>=0) { + if (originIndex >= 0) { origin.getInt(originIndex) } else { get(index) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt new file mode 100644 index 000000000..eac4f17e1 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2022 KMath 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 kotlin.test.Test + +class StridesTest { + @Test + fun checkRowBasedStrides() { + val strides = RowStrides(intArrayOf(3, 3)) + var counter = 0 + for(i in 0..2){ + for(j in 0..2){ +// print(strides.offset(intArrayOf(i,j)).toString() + "\t") + require(strides.offset(intArrayOf(i,j)) == counter) + counter++ + } + println() + } + } + + @Test + fun checkColumnBasedStrides() { + val strides = ColumnStrides(intArrayOf(3, 3)) + var counter = 0 + for(i in 0..2){ + for(j in 0..2){ +// print(strides.offset(intArrayOf(i,j)).toString() + "\t") + require(strides.offset(intArrayOf(j,i)) == counter) + counter++ + } + println() + } + } +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt index 992080fb0..04671e040 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/BufferExpandedTest.kt @@ -9,7 +9,7 @@ internal class BufferExpandedTest { @Test fun shrink(){ - val view = buffer.slice(20U..30U) + val view = buffer.slice(20..30) assertEquals(20, view[0]) assertEquals(30, view[10]) assertFails { view[11] } 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 786d32190..c217c3a26 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 @@ -8,7 +8,7 @@ package space.kscience.kmath.structures import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.StructureND public class LazyStructureND( @@ -27,7 +27,7 @@ public class LazyStructureND( @OptIn(PerformancePitfall::class) override fun elements(): Sequence> { - val strides = DefaultStrides(shape) + val strides = ColumnStrides(shape) val res = runBlocking { strides.asSequence().toList().map { index -> index to await(index) } } return res.asSequence() } 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 2cefb33a5..1c9f00838 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.FieldOpsND import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND @@ -32,7 +32,7 @@ public class HistogramND, D : Domain, V : Any>( override val dimension: Int get() = group.shape.size override val bins: Iterable> - get() = DefaultStrides(group.shape).asSequence().map { + get() = ColumnStrides(group.shape).asSequence().map { group.produceBin(it, values[it]) }.asIterable() } 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 717f9d7a1..7e11c9a2f 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 @@ -8,7 +8,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.operations.invoke import space.kscience.kmath.real.DoubleVector import kotlin.random.Random @@ -73,7 +73,7 @@ internal class MultivariateHistogramTest { } val res = histogram1 - histogram2 assertTrue { - DefaultStrides(shape).asSequence().all { index -> + ColumnStrides(shape).asSequence().all { index -> res.values[index] <= histogram1.values[index] } } diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 194c5fcee..dd0249fbc 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -31,7 +31,7 @@ public abstract class MultikTensorAlgebra>( protected val multikStat: Statistics = multikEngine.getStatistics() override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { - val strides = DefaultStrides(shape) + val strides = ColumnStrides(shape) val memoryView = initMemoryView(strides.linearSize, type) strides.asSequence().forEachIndexed { linearIndex, tensorIndex -> memoryView[linearIndex] = elementAlgebra.initializer(tensorIndex) 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 c1772683f..b0fce8dcf 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 @@ -13,7 +13,7 @@ import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.factory.ops.NDBase import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField @@ -178,7 +178,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { val array: INDArray = Nd4j.zeros(*shape) - val indices = DefaultStrides(shape) + val indices = ColumnStrides(shape) indices.asSequence().forEach { index -> array.putScalar(index, elementAlgebra.initializer(index)) } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 96ad4daf7..3cd2212f6 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -38,7 +38,7 @@ public val Series.absoluteIndices: IntRange get() = position until positi /** * A [BufferView] with index offset (both positive and negative) and possible size change */ -private class OffsetBufer( +private class SeriesImpl( override val origin: Buffer, override val position: Int, override val size: Int = origin.size, @@ -86,9 +86,9 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( * Create an offset series with index starting point at [index] */ public fun Buffer.moveTo(index: Int): Series = if (this is Series) { - OffsetBufer(origin, index, size) + SeriesImpl(origin, index, size) } else { - OffsetBufer(this, index, size) + SeriesImpl(this, index, size) } public val Buffer.offset: Int get() = if (this is Series) position else 0 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 c4d192792..953076680 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 @@ -13,7 +13,7 @@ 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.ColumnStrides import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField @@ -39,7 +39,7 @@ public class DoubleTensorFlowAlgebra internal constructor( initializer: DoubleField.(IntArray) -> Double, ): StructureND { val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array -> - DefaultStrides(shape).forEach { index -> + ColumnStrides(shape).forEach { index -> array.setDouble(elementAlgebra.initializer(index), *index.toLongArray()) } } 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 0b043db56..53f77195c 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.RowStrides import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor @@ -20,9 +21,9 @@ public abstract class BufferedTensor( public abstract val source: MutableBuffer /** - * Buffer strides based on [TensorLinearStructure] implementation + * Buffer strides based on [RowStrides] implementation */ - override val indices: Strides get() = TensorLinearStructure(shape) + override val indices: Strides get() = RowStrides(shape) /** * Number of elements in tensor 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 d3308a69f..05d2b0feb 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 @@ -5,32 +5,38 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.MutableStructureND +import space.kscience.kmath.nd.Shape import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString +import kotlin.jvm.JvmInline public class OffsetDoubleBuffer( - private val source: DoubleBuffer, + override val origin: DoubleBuffer, private val offset: Int, override val size: Int, -) : MutableBuffer { +) : MutableBuffer, BufferView { 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" } + require(offset + size <= origin.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 + origin[index + offset] = value } - override fun get(index: Int): Double = source[index + offset] + override fun get(index: Int): Double = origin[index + offset] /** * Copy only a part of buffer that belongs to this [OffsetDoubleBuffer] */ - override fun copy(): DoubleBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() + override fun copy(): DoubleBuffer = origin.array.copyOfRange(offset, offset + size).asBuffer() override fun iterator(): Iterator = iterator { for (i in indices) { @@ -41,7 +47,14 @@ public class OffsetDoubleBuffer( override fun toString(): String = Buffer.toString(this) public fun view(addOffset: Int, newSize: Int = size - addOffset): OffsetDoubleBuffer = - OffsetDoubleBuffer(source, offset + addOffset, newSize) + OffsetDoubleBuffer(origin, offset + addOffset, newSize) + + @UnstableKMathAPI + override fun originIndex(index: Int): Int = if (index in 0 until size) { + index + offset + } else { + -1 + } } public fun OffsetDoubleBuffer.slice(range: IntRange): OffsetDoubleBuffer = view(range.first, range.last - range.first) @@ -90,3 +103,59 @@ public class DoubleTensor( override fun toString(): String = toPrettyString() } + +@JvmInline +public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStructureND by tensor, + MutableStructure2D { + + init { + require(tensor.shape.size == 2) { "Only 2D tensors could be cast to 2D" } + } + + override val rowNum: Int get() = shape[0] + override val colNum: Int get() = shape[1] + + override fun get(i: Int, j: Int): Double = tensor.source[i * colNum + j] + + override fun set(i: Int, j: Int, value: Double) { + tensor.source[i * colNum + j] = value + } + + @OptIn(PerformancePitfall::class) + override val rows: List + get() = List(rowNum) { i -> + tensor.source.view(i * colNum, colNum) + } + + +// @OptIn(PerformancePitfall::class) +// override val columns: List> get() = List(colNum) { j -> +// object : MutableBuffer{ +// +// override fun get(index: Int): Double { +// tensor.source.get() +// } +// +// override fun set(index: Int, value: Double) { +// TODO("Not yet implemented") +// } +// +// override fun copy(): MutableBuffer { +// TODO("Not yet implemented") +// } +// +// override val size: Int +// get() = TODO("Not yet implemented") +// +// override fun toString(): String { +// TODO("Not yet implemented") +// } +// +// } +// } + + @PerformancePitfall + override fun elements(): Sequence> = tensor.elements() + override fun get(index: IntArray): Double = tensor[index] + override val shape: Shape get() = tensor.shape +} 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 67248890c..4c65373d8 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 @@ -11,6 +11,7 @@ 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.nd.Strides.Companion.linearSizeOf import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra @@ -121,7 +122,7 @@ public open class DoubleTensorAlgebra : */ override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( shape, - TensorLinearStructure(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() + RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) override fun Tensor.getTensor(i: Int): DoubleTensor { @@ -130,7 +131,7 @@ public open class DoubleTensorAlgebra : val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) return DoubleTensor( newShape, - dt.source.view(newShape.reduce(Int::times) * i, TensorLinearStructure.linearSizeOf(newShape)) + dt.source.view(newShape.reduce(Int::times) * i, linearSizeOf(newShape)) ) } 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 index 124ccc668..3b00744a1 100644 --- 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 @@ -119,7 +119,7 @@ public open class IntTensorAlgebra : TensorAlgebra { */ override fun structureND(shape: IntArray, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( shape, - TensorLinearStructure(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() + RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() ) override fun Tensor.getTensor(i: Int): IntTensor { 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 deleted file mode 100644 index 729fc0d13..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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.Strides -import kotlin.math.max - -/** - * This [Strides] implementation follows the last dimension first convention - * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html - * - * @param shape the shape of the tensor. - */ -public class TensorLinearStructure(override val shape: IntArray) : Strides() { - override val strides: IntArray get() = stridesFromShape(shape) - - override fun index(offset: Int): IntArray = - indexFromOffset(offset, strides, shape.size) - - override val linearSize: Int get() = linearSizeOf(shape) - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || this::class != other::class) return false - - other as TensorLinearStructure - - if (!shape.contentEquals(other.shape)) return false - - return true - } - - override fun hashCode(): Int { - return shape.contentHashCode() - } - - 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) - if (nDim == 0) - return res - - var current = nDim - 1 - res[current] = 1 - - while (current > 0) { - res[current - 1] = max(1, shape[current]) * res[current] - current-- - } - return res - } - - public fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { - val res = IntArray(nDim) - var current = offset - var strideIndex = 0 - - while (strideIndex < nDim) { - res[strideIndex] = (current / strides[strideIndex]) - current %= strides[strideIndex] - strideIndex++ - } - return res - } - } - -} \ 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 index c5910a436..daf6f5a07 100644 --- 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 @@ -5,17 +5,18 @@ 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.nd.* +import space.kscience.kmath.nd.Strides.Companion.linearSizeOf 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 space.kscience.kmath.tensors.core.BufferedTensor +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.OffsetDoubleBuffer +import space.kscience.kmath.tensors.core.copyToTensor import kotlin.math.abs import kotlin.math.max import kotlin.math.sqrt @@ -177,7 +178,7 @@ internal val DoubleTensor.matrices: VirtualBuffer val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - val size = TensorLinearStructure.linearSizeOf(matrixShape) + val size = linearSizeOf(matrixShape) return VirtualBuffer(linearSize / matrixOffset) { index -> val offset = index * matrixOffset 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 index db289a090..f938d1c61 100644 --- 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 @@ -32,20 +32,19 @@ internal fun List.concat(): IntBuffer { } -internal val IntTensor.vectors: VirtualBuffer - get() { - val n = shape.size - val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) +internal fun IntTensor.vectors(): VirtualBuffer { + 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())) - } + return VirtualBuffer(linearSize / vectorOffset) { index -> + val offset = index * vectorOffset + IntTensor(vectorShape, source.view(offset, vectorShape.first())) } +} -internal fun IntTensor.vectorSequence(): Sequence = vectors.asSequence() +internal fun IntTensor.vectorSequence(): Sequence = vectors().asSequence() internal val IntTensor.matrices: VirtualBuffer 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 cfbd9bdc9..cba81f56b 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 @@ -5,9 +5,8 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.as1D +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.DoubleBufferOps.Companion.map -import space.kscience.kmath.operations.toMutableList import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.structures.DoubleBuffer @@ -67,6 +66,7 @@ internal fun format(value: Double, digits: Int = 4): String = buildString { repeat(fLength - res.length) { append(' ') } } +@OptIn(PerformancePitfall::class) internal fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape @@ -85,7 +85,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { charOffset += 1 } - val values = vector.as1D().toMutableList().map(::format) + val values = vector.elements().map { format(it.second) } values.joinTo(this, separator = ", ") @@ -101,7 +101,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { } offset += vectorSize - if (this@toPrettyString.linearSize == offset) { + if (this@toPrettyString.indices.linearSize == offset) { break } 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 index 118624440..61bf2341e 100644 --- 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.DoubleBufferND +import space.kscience.kmath.nd.RowStrides import space.kscience.kmath.nd.StructureND import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer @@ -17,12 +18,12 @@ import space.kscience.kmath.tensors.api.Tensor */ public fun StructureND.copyToTensor(): DoubleTensor = if (this is DoubleTensor) { DoubleTensor(shape, source.copy()) -} else if (this is DoubleBufferND && indices is TensorLinearStructure) { +} else if (this is DoubleBufferND && indices is RowStrides) { DoubleTensor(shape, buffer.copy()) } else { DoubleTensor( shape, - TensorLinearStructure(this.shape).map(this::get).toDoubleArray().asBuffer(), + RowStrides(this.shape).map(this::get).toDoubleArray().asBuffer(), ) } @@ -46,7 +47,7 @@ public fun StructureND.toDoubleTensor(): DoubleTensor { */ public fun StructureND.asDoubleTensor(): DoubleTensor = if (this is DoubleTensor) { this -} else if (this is DoubleBufferND && indices is TensorLinearStructure) { +} else if (this is DoubleBufferND && indices is RowStrides) { DoubleTensor(shape, buffer) } else { copyToTensor() @@ -59,6 +60,6 @@ public fun StructureND.asIntTensor(): IntTensor = when (this) { is IntTensor -> this else -> IntTensor( this.shape, - TensorLinearStructure(this.shape).map(this::get).toIntArray().asBuffer() + RowStrides(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/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index c87cf2a68..5261fab8c 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 @@ -66,7 +66,7 @@ internal class TestDoubleTensor { val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray: MutableBufferND = DoubleBufferND(DefaultStrides(intArrayOf(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(intArrayOf(3)), doubleArray) // map to tensors val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. 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 493af54c9..1b7601a14 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 @@ -33,7 +33,7 @@ public open class ViktorFieldOpsND : override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = F64Array(*shape).apply { - DefaultStrides(shape).asSequence().forEach { index -> + ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.initializer(index), indices = index) } }.asStructure() @@ -43,7 +43,7 @@ public open class ViktorFieldOpsND : @PerformancePitfall override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = F64Array(*shape).apply { - DefaultStrides(shape).asSequence().forEach { index -> + ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.transform(this@map[index]), indices = index) } }.asStructure() @@ -52,7 +52,7 @@ public open class ViktorFieldOpsND : override fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): ViktorStructureND = F64Array(*shape).apply { - DefaultStrides(shape).asSequence().forEach { index -> + ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) } }.asStructure() @@ -65,7 +65,7 @@ public open class ViktorFieldOpsND : ): ViktorStructureND { require(left.shape.contentEquals(right.shape)) return F64Array(*left.shape).apply { - DefaultStrides(left.shape).asSequence().forEach { index -> + ColumnStrides(left.shape).asSequence().forEach { index -> set(value = DoubleField.transform(left[index], right[index]), indices = index) } }.asStructure() 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 c9749d41a..ea279a912 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.MutableStructureND @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @@ -22,7 +22,7 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur @PerformancePitfall override fun elements(): Sequence> = - DefaultStrides(shape).asSequence().map { it to get(it) } + ColumnStrides(shape).asSequence().map { it to get(it) } } public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) From 89d0cbc7ea92bdace8920ce401c30825d48d5949 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 30 Sep 2022 11:34:44 +0300 Subject: [PATCH 11/72] Refactoring and optimization of tensorAlgebra --- .../kscience/kmath/structures/BufferView.kt | 43 +++++++++++++- .../kmath/tensors/core/DoubleTensor.kt | 58 ++++++++++--------- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 24 ++++---- .../core/internal/doubleTensorHelpers.kt | 10 ++-- .../kmath/tensors/core/internal/linUtils.kt | 18 +++--- .../kmath/tensors/core/internal/utils.kt | 8 +-- .../kmath/tensors/core/TestDoubleTensor.kt | 24 +++++++- 7 files changed, 126 insertions(+), 59 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt index e8ab4f0ba..697939bdf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferView.kt @@ -148,4 +148,45 @@ public class PermutedBuffer( /** * Created a permuted view of given buffer using provided [indices] */ -public fun Buffer.permute(indices: IntArray): PermutedBuffer = PermutedBuffer(this, indices) \ No newline at end of file +public fun Buffer.permute(indices: IntArray): PermutedBuffer = + PermutedBuffer(this, indices) + +/** + * A [BufferView] that overrides indexing of the original buffer + */ +public class PermutedMutableBuffer( + override val origin: MutableBuffer, + private val permutations: IntArray, +) : BufferView, MutableBuffer { + init { + permutations.forEach { index -> + if (index !in origin.indices) { + throw IndexOutOfBoundsException("Index $index is not in ${origin.indices}") + } + } + } + + override val size: Int get() = permutations.size + + override fun get(index: Int): T = origin[permutations[index]] + + override fun set(index: Int, value: T) { + origin[permutations[index]] = value + } + + override fun copy(): MutableBuffer = PermutedMutableBuffer(origin.copy(), permutations) + //TODO Probably could be optimized + + override fun iterator(): Iterator = permutations.asSequence().map { origin[it] }.iterator() + + @UnstableKMathAPI + override fun originIndex(index: Int): Int = if (index in permutations.indices) permutations[index] else -1 + + override fun toString(): String = Buffer.toString(this) +} + +/** + * Created a permuted mutable view of given buffer using provided [indices] + */ +public fun MutableBuffer.permute(indices: IntArray): PermutedMutableBuffer = + PermutedMutableBuffer(this, indices) \ No newline at end of file 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 05d2b0feb..470b6070b 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 @@ -10,6 +10,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.MutableStructureND import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString import kotlin.jvm.JvmInline @@ -81,7 +82,9 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { } /** - * Default [BufferedTensor] implementation for [Double] values + * Default [BufferedTensor] implementation for [Double] values. + * + * [DoubleTensor] always uses row-based strides */ public class DoubleTensor( shape: IntArray, @@ -128,34 +131,37 @@ public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStru } -// @OptIn(PerformancePitfall::class) -// override val columns: List> get() = List(colNum) { j -> -// object : MutableBuffer{ -// -// override fun get(index: Int): Double { -// tensor.source.get() -// } -// -// override fun set(index: Int, value: Double) { -// TODO("Not yet implemented") -// } -// -// override fun copy(): MutableBuffer { -// TODO("Not yet implemented") -// } -// -// override val size: Int -// get() = TODO("Not yet implemented") -// -// override fun toString(): String { -// TODO("Not yet implemented") -// } -// -// } -// } + @OptIn(PerformancePitfall::class) + override val columns: List> + get() = List(colNum) { j -> + val indices = IntArray(rowNum) { i -> j + i * colNum } + tensor.source.permute(indices) + } @PerformancePitfall override fun elements(): Sequence> = tensor.elements() override fun get(index: IntArray): Double = tensor[index] override val shape: Shape get() = tensor.shape } + +public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D = DoubleTensor2D(this) + +public fun DoubleTensor.asDoubleBuffer(): OffsetDoubleBuffer = if(shape.size == 1){ + source +} else { + error("Only 1D tensors could be cast to 1D" ) +} + +public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: DoubleTensor2D) -> Unit) { + 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 = Strides.linearSizeOf(matrixShape) + for (i in 0 until linearSize / matrixOffset) { + val offset = i * matrixOffset + val index = indices.index(offset).sliceArray(0 until (shape.size - 2)) + block(index, DoubleTensor(matrixShape, source.view(offset, size)).asDoubleTensor2D()) + } +} 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 4c65373d8..71e55a3b9 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 @@ -496,7 +496,7 @@ public open class DoubleTensorAlgebra : * with `0.0` mean and `1.0` standard deviation. */ public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = - DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) + DoubleTensor(shape, DoubleBuffer.randomNormals(shape.reduce(Int::times), seed)) /** * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions @@ -508,7 +508,7 @@ public open class DoubleTensorAlgebra : * with `0.0` mean and `1.0` standard deviation. */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = - DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) + DoubleTensor(shape, DoubleBuffer.randomNormals(shape.reduce(Int::times), seed)) /** * Concatenates a sequence of tensors with equal shapes along the first dimension. @@ -781,7 +781,7 @@ public open class DoubleTensorAlgebra : pTensor .matrixSequence() .zip(pivotsTensor.asIntTensor().vectorSequence()) - .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } + .forEach { (p, pivot) -> pivInit(p.asDoubleTensor2D(), pivot.as1D(), n) } val lTensor = zeroesLike(luTensor) val uTensor = zeroesLike(luTensor) @@ -791,7 +791,7 @@ public open class DoubleTensorAlgebra : .zip(luTensor.asDoubleTensor().matrixSequence()) .forEach { (pairLU, lu) -> val (l, u) = pairLU - luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) + luPivotHelper(l.asDoubleTensor2D(), u.asDoubleTensor2D(), lu.asDoubleTensor2D(), n) } return Triple(pTensor, lTensor, uTensor) @@ -818,7 +818,7 @@ public open class DoubleTensorAlgebra : val lTensor = zeroesLike(this) for ((a, l) in asDoubleTensor().matrixSequence().zip(lTensor.matrixSequence())) - for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) + for (i in 0 until n) choleskyHelper(a.asDoubleTensor2D(), l.asDoubleTensor2D(), n) return lTensor } @@ -837,7 +837,7 @@ public open class DoubleTensorAlgebra : .zip(rTensor.matrixSequence())) ).forEach { (matrix, qr) -> val (q, r) = qr - qrHelper(matrix, q, r.as2D()) + qrHelper(matrix, q, r.asDoubleTensor2D()) } return qTensor to rTensor @@ -867,7 +867,7 @@ public open class DoubleTensorAlgebra : val sTensor = zeros(commonShape + intArrayOf(min(n, m))) val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - val matrices: VirtualBuffer = asDoubleTensor().matrices + val matrices = asDoubleTensor().matrices val uTensors = uTensor.matrices val sTensorVectors = sTensor.vectors val vTensors = vTensor.matrices @@ -922,7 +922,7 @@ public open class DoubleTensorAlgebra : val utv = u.transposed() matmul v val n = s.shape.last() for (matrix in utv.matrixSequence()) { - matrix.as2D().cleanSym(n) + matrix.asDoubleTensor2D().cleanSym(n) } val eig = (utv dot s.view(shp)).view(s.shape) @@ -940,7 +940,7 @@ public open class DoubleTensorAlgebra : var eigenvalueStart = 0 var eigenvectorStart = 0 for (matrix in asDoubleTensor().matrixSequence()) { - val matrix2D = matrix.as2D() + val matrix2D = matrix.asDoubleTensor2D() val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) for (i in 0 until matrix2D.rowNum) { @@ -986,8 +986,8 @@ public open class DoubleTensorAlgebra : ) luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) - 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) + resBuffer[index] = if (luHelper(lu.asDoubleTensor2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.asDoubleTensor2D(), pivots.as1D()) } return detTensor @@ -1010,7 +1010,7 @@ public open class DoubleTensorAlgebra : val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) for ((luP, invMatrix) in seq) { val (lu, pivots) = luP - luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) + luMatrixInv(lu.asDoubleTensor2D(), pivots.as1D(), invMatrix.asDoubleTensor2D()) } return invTensor 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 index daf6f5a07..22047e458 100644 --- 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 @@ -7,9 +7,7 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.* import space.kscience.kmath.nd.Strides.Companion.linearSizeOf -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.BroadcastDoubleTensorAlgebra.eye @@ -155,13 +153,13 @@ internal fun List.concat(): DoubleBuffer { return array.asBuffer() } -internal val DoubleTensor.vectors: VirtualBuffer +internal val DoubleTensor.vectors: List get() { val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) - return VirtualBuffer(linearSize / vectorOffset) { index -> + return List(linearSize / vectorOffset) { index -> val offset = index * vectorOffset DoubleTensor(vectorShape, source.view(offset, vectorShape.first())) } @@ -171,7 +169,7 @@ internal val DoubleTensor.vectors: VirtualBuffer internal fun DoubleTensor.vectorSequence(): Sequence = vectors.asSequence() -internal val DoubleTensor.matrices: VirtualBuffer +internal val DoubleTensor.matrices: List get() { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } @@ -180,7 +178,7 @@ internal val DoubleTensor.matrices: VirtualBuffer val size = linearSizeOf(matrixShape) - return VirtualBuffer(linearSize / matrixOffset) { index -> + return List(linearSize / matrixOffset) { index -> val offset = index * matrixOffset DoubleTensor(matrixShape, source.view(offset, size)) } 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 9047ba29e..cc699e1bb 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 @@ -5,8 +5,12 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.as1D import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.IntBuffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.indices @@ -109,7 +113,7 @@ internal fun DoubleTensorAlgebra.computeLU( val pivotsTensor = tensor.setUpPivots() for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) + if (luHelper(lu.asDoubleTensor2D(), pivots.as1D(), epsilon)) return null return Pair(luTensor, pivotsTensor) @@ -210,18 +214,18 @@ internal fun DoubleTensorAlgebra.qrHelper( ) { checkSquareMatrix(matrix.shape) val n = matrix.shape[0] - val qM = q.as2D() + val qM = q.asDoubleTensor2D() val matrixT = matrix.transposed(0, 1) val qT = q.transposed(0, 1) for (j in 0 until n) { val v = matrixT.getTensor(j) - val vv = v.as1D() + val vv = v.asDoubleBuffer() if (j > 0) { for (i in 0 until j) { r[i, j] = (qT.getTensor(i) dot matrixT.getTensor(j)).value() for (k in 0 until n) { - val qTi = qT.getTensor(i).as1D() + val qTi = qT.getTensor(i).asDoubleBuffer() vv[k] = vv[k] - r[i, j] * qTi[k] } } @@ -239,10 +243,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) val b: DoubleTensor if (n > m) { b = a.transposed(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), getRandomUnitVector(m, 0)) + v = DoubleTensor(intArrayOf(m), DoubleBuffer.randomUnitVector(m, 0)) } else { b = a.dot(a.transposed(0, 1)) - v = DoubleTensor(intArrayOf(n), getRandomUnitVector(n, 0)) + v = DoubleTensor(intArrayOf(n), DoubleBuffer.randomUnitVector(n, 0)) } var lastV: DoubleTensor 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 cba81f56b..c5ba98811 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 @@ -14,14 +14,14 @@ import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.* -internal fun getRandomNormals(n: Int, seed: Long): DoubleBuffer { +internal fun DoubleBuffer.Companion.randomNormals(n: Int, seed: Long): DoubleBuffer { val distribution = GaussianSampler(0.0, 1.0) val generator = RandomGenerator.default(seed) return distribution.sample(generator).nextBufferBlocking(n) } -internal fun getRandomUnitVector(n: Int, seed: Long): DoubleBuffer { - val unnorm: DoubleBuffer = getRandomNormals(n, seed) +internal fun DoubleBuffer.Companion.randomUnitVector(n: Int, seed: Long): DoubleBuffer { + val unnorm: DoubleBuffer = randomNormals(n, seed) val norm = sqrt(unnorm.array.sumOf { it * it }) return unnorm.map { it / norm } } @@ -67,7 +67,7 @@ internal fun format(value: Double, digits: Int = 4): String = buildString { } @OptIn(PerformancePitfall::class) -internal fun DoubleTensor.toPrettyString(): String = buildString { +public fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.indices 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 5261fab8c..505031b67 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 @@ -11,6 +11,7 @@ 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.matrixSequence +import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -38,7 +39,7 @@ internal class TestDoubleTensor { @Test fun testGet() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) - val matrix = tensor.getTensor(0).as2D() + val matrix = tensor.getTensor(0).asDoubleTensor2D() assertEquals(matrix[0, 1], 5.8) val vector = tensor.getTensor(0, 1).as1D() @@ -52,8 +53,8 @@ internal class TestDoubleTensor { tensor.matrixSequence().forEach { val a = it.asDoubleTensor() - val secondRow = a.getTensor(1).as1D() - val secondColumn = a.transposed(0, 1).getTensor(1).as1D() + val secondRow = a.getTensor(1).asDoubleBuffer() + val secondColumn = a.transposed(0, 1).getTensor(1).asDoubleBuffer() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } @@ -86,6 +87,23 @@ internal class TestDoubleTensor { tensorArray[intArrayOf(0)] = 55.9 assertEquals(ndArray[intArrayOf(0)], 1.0) + } + @Test + fun test2D() = with(DoubleTensorAlgebra) { + val tensor: DoubleTensor = structureND(intArrayOf(3, 3)) { (i, j) -> (i - j).toDouble() } + //println(tensor.toPrettyString()) + val tensor2d = tensor.asDoubleTensor2D() + assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1]) + assertBufferEquals(DoubleBuffer(-2.0, -1.0, 0.0), tensor2d.columns[2]) + } + + @Test + fun testMatrixIteration() = with(DoubleTensorAlgebra) { + val tensor = structureND(intArrayOf(3, 3, 3, 3)) { index -> index.sum().toDouble() } + tensor.forEachMatrix { index, matrix -> + println(index.joinToString { it.toString() }) + println(matrix) + } } } From b0abcf2d0c0d468f927dffe277e525e7cf678847 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 Oct 2022 12:47:57 +0300 Subject: [PATCH 12/72] Safe shapes --- CHANGELOG.md | 1 + .../kmath/benchmarks/NDFieldBenchmark.kt | 11 +- build.gradle.kts | 14 +- .../kmath/structures/StreamDoubleFieldND.kt | 5 +- .../structures/StructureReadBenchmark.kt | 5 +- .../structures/StructureWriteBenchmark.kt | 12 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 16 +- .../space/kscience/kmath/tensors/PCA.kt | 9 +- .../kmath/tensors/dataSetNormalization.kt | 5 +- .../tensors/linearSystemSolvingWithLUP.kt | 7 +- .../kscience/kmath/tensors/neuralNetwork.kt | 12 +- gradle.properties | 4 +- .../kscience/kmath/complex/ComplexFieldND.kt | 6 +- .../kmath/linear/BufferedLinearSpace.kt | 6 +- .../kmath/linear/DoubleLinearSpace.kt | 6 +- .../kscience/kmath/linear/VirtualMatrix.kt | 4 +- .../space/kscience/kmath/misc/annotations.kt | 13 ++ .../kscience/kmath/nd/BufferAlgebraND.kt | 15 +- .../space/kscience/kmath/nd/BufferND.kt | 74 ++++---- .../space/kscience/kmath/nd/DoubleFieldND.kt | 17 +- .../space/kscience/kmath/nd/IntRingND.kt | 2 +- .../kscience/kmath/nd/PermutedStructureND.kt | 50 ++++++ .../kotlin/space/kscience/kmath/nd/Shape.kt | 83 ++++++++- .../space/kscience/kmath/nd/ShapeIndices.kt | 17 +- .../space/kscience/kmath/nd/ShortRingND.kt | 2 +- .../space/kscience/kmath/nd/Structure1D.kt | 15 +- .../space/kscience/kmath/nd/Structure2D.kt | 7 +- .../space/kscience/kmath/nd/StructureND.kt | 19 +- .../kscience/kmath/nd/VirtualStructureND.kt | 3 + .../space/kscience/kmath/nd/operationsND.kt | 4 + .../kscience/kmath/nd/primitiveStructureND.kt | 45 +++++ .../kmath/structures/BufferAccessor2D.kt | 7 +- .../space/kscience/kmath/nd/StridesTest.kt | 4 +- .../kmath/structures/NumberNDFieldTest.kt | 2 +- .../kmath/structures/LazyStructureND.kt | 4 +- .../kscience/kmath/dimensions/Wrappers.kt | 3 +- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 3 +- .../kscience/kmath/histogram/HistogramND.kt | 3 + .../histogram/UniformHistogramGroupND.kt | 18 +- .../histogram/MultivariateHistogramTest.kt | 2 + .../kscience/kmath/multik/MultikTensor.kt | 4 +- .../kmath/multik/MultikTensorAlgebra.kt | 39 +++-- .../kscience/kmath/multik/MultikNDTest.kt | 5 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 30 ++-- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 27 ++- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 22 +-- .../kmath/nd4j/Nd4jArrayStructureTest.kt | 3 +- .../tensorflow/DoubleTensorFlowAlgebra.kt | 2 + .../kmath/tensorflow/TensorFlowAlgebra.kt | 20 ++- .../kmath/tensorflow/DoubleTensorFlowOps.kt | 5 +- .../tensors/api/LinearOpsTensorAlgebra.kt | 14 +- .../kmath/tensors/api/TensorAlgebra.kt | 9 +- .../kmath/tensors/core/BufferedTensor.kt | 3 +- .../kmath/tensors/core/DoubleTensor.kt | 30 ++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 162 ++++++++++-------- .../kscience/kmath/tensors/core/IntTensor.kt | 8 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 101 ++++++----- .../tensors/core/internal/broadcastUtils.kt | 27 +-- .../kmath/tensors/core/internal/checks.kt | 21 ++- .../core/internal/doubleTensorHelpers.kt | 15 +- .../tensors/core/internal/intTensorHelpers.kt | 7 +- .../kmath/tensors/core/internal/linUtils.kt | 13 +- .../kmath/tensors/core/internal/utils.kt | 4 +- .../tensors/core/tensorAlgebraExtensions.kt | 4 +- .../kmath/tensors/core/tensorTransform.kt | 12 +- .../kmath/tensors/core/TestBroadcasting.kt | 64 +++---- .../core/TestDoubleAnalyticTensorAlgebra.kt | 21 +-- .../core/TestDoubleLinearOpsAlgebra.kt | 38 ++-- .../kmath/tensors/core/TestDoubleTensor.kt | 12 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 84 ++++----- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 31 ++-- .../kmath/viktor/ViktorStructureND.kt | 5 +- 72 files changed, 860 insertions(+), 517 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index feb925436..eea1dd3ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed +- Shape is read-only - Major refactor of tensors (only minor API changes) - Kotlin 1.7.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style 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 141d0433b..75c1a3ee3 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -13,10 +13,8 @@ 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.nd.BufferedFieldOpsND -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.ndAlgebra -import space.kscience.kmath.nd.one +import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.nd.* import space.kscience.kmath.nd4j.nd4j import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.tensors.core.DoubleTensor @@ -69,9 +67,10 @@ internal class NDFieldBenchmark { blackhole.consume(res) } + @OptIn(UnsafeKMathAPI::class) @Benchmark fun multikInPlaceAdd(blackhole: Blackhole) = with(multikAlgebra) { - val res = Multik.ones(shape, DataType.DoubleDataType).wrap() + val res = Multik.ones(shape.asArray(), DataType.DoubleDataType).wrap() repeat(n) { res += 1.0 } blackhole.consume(res) } @@ -86,7 +85,7 @@ internal class NDFieldBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = intArrayOf(dim, dim) + private val shape = Shape(dim, dim) private val specializedField = DoubleField.ndAlgebra private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j diff --git a/build.gradle.kts b/build.gradle.kts index 120b0f35d..c7e2e5892 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import space.kscience.gradle.isInDevelopment import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useSPCTeam @@ -15,7 +14,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-4" + version = "0.3.1-dev-5" } subprojects { @@ -78,11 +77,12 @@ ksciencePublish { } 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" - } + "https://maven.pkg.jetbrains.space/spc/p/sci/maven" +// if (isInDevelopment) { +// "https://maven.pkg.jetbrains.space/spc/p/sci/dev" +// } else { +// "https://maven.pkg.jetbrains.space/spc/p/sci/release" +// } ) sonatype() } 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 f97e98973..dd1516fcd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -17,7 +17,7 @@ import java.util.stream.IntStream * A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel * execution. */ -class StreamDoubleFieldND(override val shape: IntArray) : FieldND, +class StreamDoubleFieldND(override val shape: Shape) : FieldND, NumbersAddOps>, ExtendedField> { @@ -31,6 +31,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND.buffer: DoubleBuffer get() = when { !shape.contentEquals(this@StreamDoubleFieldND.shape) -> throw ShapeMismatchException( @@ -110,4 +111,4 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND): BufferND = arg.map { atanh(it) } } -fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape) +fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(Shape(shape)) 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 ae7693f03..ec05f38d0 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -5,16 +5,19 @@ package space.kscience.kmath.structures +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.ColumnStrides +import space.kscience.kmath.nd.Shape import kotlin.system.measureTimeMillis @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") +@OptIn(PerformancePitfall::class) fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } val buffer = DoubleBuffer(array) - val strides = ColumnStrides(intArrayOf(n, n)) + val strides = ColumnStrides(Shape(n, n)) val structure = BufferND(strides, buffer) measureTimeMillis { 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 ce5301a7b..081bfa5c0 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -5,16 +5,20 @@ package space.kscience.kmath.structures +import space.kscience.kmath.nd.BufferND +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.mapToBuffer +import space.kscience.kmath.operations.map import kotlin.system.measureTimeMillis +private inline fun BufferND.map(block: (T) -> R): BufferND = BufferND(indices, buffer.map(block)) + @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 - val structure = StructureND.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } - structure.mapToBuffer { it + 1 } // warm-up - val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } } + val structure = StructureND.buffered(Shape(n, n), Buffer.Companion::auto) { 1.0 } + structure.map { it + 1 } // warm-up + val time1 = measureTimeMillis { val res = structure.map { it + 1 } } println("Structure mapping finished in $time1 millis") val array = DoubleArray(n * n) { 1.0 } 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 d0b24de70..32d4176c1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -6,6 +6,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra @@ -23,10 +25,10 @@ fun main() { DoubleTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( - intArrayOf(5), + Shape(5), randSeed ) + fromArray( - intArrayOf(5), + Shape(5), doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) ) @@ -34,7 +36,7 @@ fun main() { // also take sample of size 20 from normal distribution for x val x = randomNormal( - intArrayOf(20, 5), + Shape(20, 5), randSeed ) @@ -50,11 +52,13 @@ 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 sigma = diagonalEmbedding(singValues.map { if (abs(it) < 1e-3) 0.0 else 1.0 / it }) val alphaOLS = v dot sigma dot u.transposed() dot y - println("Estimated alpha:\n" + - "$alphaOLS") + println( + "Estimated alpha:\n" + + "$alphaOLS" + ) // figure out MSE of approximation fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double { 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 1768be283..2022b6472 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.Shape import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -16,7 +17,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // assume x is range from 0 until 10 val x = fromArray( - intArrayOf(10), + Shape(10), DoubleArray(10) { it.toDouble() } ) @@ -41,13 +42,13 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // save means ans standard deviations for further recovery val mean = fromArray( - intArrayOf(2), + Shape(2), doubleArrayOf(xMean, yMean) ) println("Means:\n$mean") val std = fromArray( - intArrayOf(2), + Shape(2), doubleArrayOf(xStd, yStd) ) println("Standard deviations:\n$std") @@ -68,7 +69,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.getTensor(n) dot v.view(intArrayOf(1, 2))) * std + mean + val restored = (datasetReduced.getTensor(n) dot v.view(Shape(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 6d72fd623..248266edb 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.Shape import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -13,10 +14,10 @@ import space.kscience.kmath.tensors.core.withBroadcast fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods // take dataset of 5-element vectors from normal distribution - val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) + val dataset = randomNormal(Shape(100, 5)) * 1.5 // all elements from N(0, 1.5) dataset += fromArray( - intArrayOf(5), + Shape(5), doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means ) 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 64cc138d7..3eab64429 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.Shape import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -15,13 +16,13 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // set true value of x val trueX = fromArray( - intArrayOf(4), + Shape(4), doubleArrayOf(-2.0, 1.5, 6.8, -2.4) ) // and A matrix val a = fromArray( - intArrayOf(4, 4), + Shape(4, 4), doubleArrayOf( 0.5, 10.5, 4.5, 1.0, 8.5, 0.9, 12.8, 0.1, @@ -64,7 +65,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // this function returns solution x of a system lx = b, l should be lower triangular fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { val n = l.shape[0] - val x = zeros(intArrayOf(n)) + val x = zeros(Shape(n)) for (i in 0 until n) { x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)] } 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 84d6dcd22..1e4e339dc 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra @@ -68,12 +70,12 @@ class Dense( private val weights: DoubleTensor = DoubleTensorAlgebra { randomNormal( - intArrayOf(inputUnits, outputUnits), + Shape(inputUnits, outputUnits), seed ) * sqrt(2.0 / (inputUnits + outputUnits)) } - private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) } + private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(Shape(outputUnits)) } override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { (input dot weights) + bias @@ -182,17 +184,17 @@ fun main() = BroadcastDoubleTensorAlgebra { //val testSize = sampleSize - trainSize // take sample of features from normal distribution - val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 + val x = randomNormal(Shape(sampleSize, features), seed) * 2.5 x += fromArray( - intArrayOf(5), + Shape(5), doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means ) // define class like '1' if the sum of features > 0 and '0' otherwise val y = fromArray( - intArrayOf(sampleSize, 1), + Shape(sampleSize, 1), DoubleArray(sampleSize) { i -> if (x.getTensor(i).sum() > 0.0) { 1.0 diff --git a/gradle.properties b/gradle.properties index 0d1506980..216ebf74a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,13 +3,11 @@ # 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 -kotlin.jupyter.add.scanner=false kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true kotlin.incremental.js.ir=true org.gradle.configureondemand=true -org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.13.0-kotlin-1.7.20-Beta +toolsVersion=0.13.1-kotlin-1.7.20 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 42914ed5b..cbc69ca6e 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 @@ -5,6 +5,7 @@ package space.kscience.kmath.complex +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -20,6 +21,7 @@ import kotlin.contracts.contract public sealed class ComplexFieldOpsND : BufferedFieldOpsND(ComplexField.bufferAlgebra), ScaleOperations>, ExtendedFieldOps>, PowerOperations> { + @OptIn(PerformancePitfall::class) override fun StructureND.toBufferND(): BufferND = when (this) { is BufferND -> this else -> { @@ -69,12 +71,12 @@ public class ComplexFieldND(override val shape: Shape) : public val ComplexField.ndAlgebra: ComplexFieldOpsND get() = ComplexFieldOpsND -public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(shape) +public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(Shape(shape)) /** * Produce a context for n-dimensional operations inside this real field */ public inline fun ComplexField.withNdAlgebra(vararg shape: Int, action: ComplexFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ComplexFieldND(shape).action() + return ComplexFieldND(Shape(shape)).action() } 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 361d59be1..52f04d76a 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 @@ -6,9 +6,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.BufferedRingOpsND -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.nd.asND +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer @@ -23,7 +21,7 @@ public class BufferedLinearSpace>( private val ndAlgebra = BufferedRingOpsND(bufferAlgebra) override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = - ndAlgebra.structureND(intArrayOf(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() + ndAlgebra.structureND(Shape(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() override fun buildVector(size: Int, initializer: A.(Int) -> T): Point = bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) } 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 e2f81d84e..47ab5bece 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 @@ -6,9 +6,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DoubleFieldOpsND -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.nd.asND +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke @@ -23,7 +21,7 @@ public object DoubleLinearSpace : LinearSpace { rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double - ): Matrix = DoubleFieldOpsND.structureND(intArrayOf(rows, columns)) { (i, j) -> + ): Matrix = DoubleFieldOpsND.structureND(Shape(rows, columns)) { (i, j) -> DoubleField.initializer(i, j) }.as2D() 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 eb5e20856..b7ed6e867 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.linear +import space.kscience.kmath.nd.Shape + /** * The matrix where each element is evaluated each time when is being accessed. * @@ -16,7 +18,7 @@ public class VirtualMatrix( public val generator: (i: Int, j: Int) -> T, ) : Matrix { - override val shape: IntArray get() = intArrayOf(rowNum, colNum) + override val shape: Shape get() = Shape(rowNum, colNum) override operator fun get(i: Int, j: Int): T = generator(i, j) } 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 f7b486850..7da333a45 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 @@ -29,3 +29,16 @@ public annotation class UnstableKMathAPI public annotation class PerformancePitfall( val message: String = "Potential performance problem", ) + +/** + * Marks API that is public, but should not be used without clear understanding what it does. + */ +@MustBeDocumented +@Retention(value = AnnotationRetention.BINARY) +@RequiresOptIn( + "This API is unsafe and should be used carefully", + RequiresOptIn.Level.ERROR, +) +public annotation class UnsafeKMathAPI( + val message: String = "Unsafe API", +) 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 4025ba548..597fc7d97 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 @@ -12,7 +12,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* public interface BufferAlgebraND> : AlgebraND { - public val indexerBuilder: (IntArray) -> ShapeIndexer + public val indexerBuilder: (Shape) -> ShapeIndexer public val bufferAlgebra: BufferAlgebra override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra @@ -26,6 +26,7 @@ public interface BufferAlgebraND> : AlgebraND { ) } + @OptIn(PerformancePitfall::class) public fun StructureND.toBufferND(): BufferND = when (this) { is BufferND -> this else -> { @@ -46,7 +47,7 @@ public interface BufferAlgebraND> : AlgebraND { zipInline(left.toBufferND(), right.toBufferND(), transform) public companion object { - public val defaultIndexerBuilder: (IntArray) -> ShapeIndexer = ::Strides + public val defaultIndexerBuilder: (Shape) -> ShapeIndexer = ::Strides } } @@ -98,24 +99,24 @@ internal inline fun > BufferAlgebraND.zipInline( @OptIn(PerformancePitfall::class) public open class BufferedGroupNDOps>( override val bufferAlgebra: BufferAlgebra, - override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + override val indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : GroupOpsND, BufferAlgebraND { override fun StructureND.unaryMinus(): StructureND = map { -it } } public open class BufferedRingOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedGroupNDOps(bufferAlgebra, indexerBuilder), RingOpsND public open class BufferedFieldOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedRingOpsND(bufferAlgebra, indexerBuilder), FieldOpsND { public constructor( elementAlgebra: A, - indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : this(BufferFieldOps(elementAlgebra), indexerBuilder) @OptIn(PerformancePitfall::class) @@ -130,7 +131,7 @@ public val > BufferAlgebra.nd: BufferedFieldOpsND ge public fun > BufferAlgebraND.structureND( vararg shape: Int, initializer: A.(IntArray) -> T, -): BufferND = structureND(shape, initializer) +): BufferND = structureND(Shape(shape), initializer) public fun , A> A.structureND( initializer: EA.(IntArray) -> T, 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 7efc785fb..644b62ebe 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 @@ -5,10 +5,9 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.MutableBufferFactory /** * Represents [StructureND] over [Buffer]. @@ -22,32 +21,33 @@ public open class BufferND( public open val buffer: Buffer, ) : StructureND { + @PerformancePitfall override operator fun get(index: IntArray): T = buffer[indices.offset(index)] - override val shape: IntArray get() = indices.shape + override val shape: Shape get() = indices.shape override fun toString(): String = StructureND.toString(this) } -/** - * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] - */ -public inline fun StructureND.mapToBuffer( - factory: BufferFactory, - crossinline transform: (T) -> R, -): BufferND = if (this is BufferND) - BufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) -else { - val strides = ColumnStrides(shape) - BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) -} - -/** - * Transform structure to a new structure using inferred [BufferFactory] - */ -public inline fun StructureND.mapToBuffer( - crossinline transform: (T) -> R, -): BufferND = mapToBuffer(Buffer.Companion::auto, transform) +///** +// * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] +// */ +//public inline fun StructureND.mapToBuffer( +// factory: BufferFactory, +// crossinline transform: (T) -> R, +//): BufferND = if (this is BufferND) +// BufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) +//else { +// val strides = ColumnStrides(shape) +// BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) +//} +// +///** +// * Transform structure to a new structure using inferred [BufferFactory] +// */ +//public inline fun StructureND.mapToBuffer( +// crossinline transform: (T) -> R, +//): BufferND = mapToBuffer(Buffer.Companion::auto, transform) /** * Represents [MutableStructureND] over [MutableBuffer]. @@ -60,22 +60,24 @@ public open class MutableBufferND( strides: ShapeIndexer, override val buffer: MutableBuffer, ) : MutableStructureND, BufferND(strides, buffer) { + + @PerformancePitfall override fun set(index: IntArray, value: T) { buffer[indices.offset(index)] = value } } -/** - * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] - */ -public inline fun MutableStructureND.mapToMutableBuffer( - factory: MutableBufferFactory = MutableBufferFactory(MutableBuffer.Companion::auto), - crossinline transform: (T) -> R, -): MutableBufferND { - return if (this is MutableBufferND) - MutableBufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) - else { - val strides = ColumnStrides(shape) - MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) - } -} \ No newline at end of file +///** +// * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] +// */ +//public inline fun MutableStructureND.mapToMutableBuffer( +// factory: MutableBufferFactory = MutableBufferFactory(MutableBuffer.Companion::auto), +// crossinline transform: (T) -> R, +//): MutableBufferND { +// return if (this is MutableBufferND) +// MutableBufferND(this.indices, factory.invoke(indices.linearSize) { transform(buffer[it]) }) +// else { +// val strides = ColumnStrides(shape) +// MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) +// } +//} \ No newline at end of file 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 aab137321..182ce38d6 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 @@ -14,15 +14,25 @@ import kotlin.contracts.contract import kotlin.math.pow import kotlin.math.pow as kpow +/** + * A simple mutable [StructureND] of doubles + */ public class DoubleBufferND( indexes: ShapeIndexer, override val buffer: DoubleBuffer, -) : MutableBufferND(indexes, buffer) +) : MutableBufferND(indexes, buffer), MutableStructureNDOfDouble{ + override fun getDouble(index: IntArray): Double = buffer[indices.offset(index)] + + override fun setDouble(index: IntArray, value: Double) { + buffer[indices.offset(index)] = value + } +} public sealed class DoubleFieldOpsND : BufferedFieldOpsND(DoubleField.bufferAlgebra), ScaleOperations>, ExtendedFieldOps> { + @OptIn(PerformancePitfall::class) override fun StructureND.toBufferND(): DoubleBufferND = when (this) { is DoubleBufferND -> this else -> { @@ -221,7 +231,8 @@ public class DoubleFieldND(override val shape: Shape) : public val DoubleField.ndAlgebra: DoubleFieldOpsND get() = DoubleFieldOpsND -public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(shape) +public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(Shape(shape)) +public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field @@ -229,5 +240,5 @@ public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleField @UnstableKMathAPI public inline fun DoubleField.withNdAlgebra(vararg shape: Int, action: DoubleFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return DoubleFieldND(shape).run(action) + return DoubleFieldND(Shape(shape)).run(action) } 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 index ac01239a9..697e351d2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt @@ -46,5 +46,5 @@ public class IntRingND( public inline fun IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return IntRingND(shape).run(action) + return IntRingND(Shape(shape)).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt new file mode 100644 index 000000000..0efc7beb0 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.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.PerformancePitfall + + +public class PermutedStructureND( + public val origin: StructureND, + public val permutation: (IntArray) -> IntArray, +) : StructureND { + + override val shape: Shape + get() = origin.shape + + @OptIn(PerformancePitfall::class) + override fun get(index: IntArray): T { + return origin[permutation(index)] + } +} + +public fun StructureND.permute( + permutation: (IntArray) -> IntArray, +): PermutedStructureND = PermutedStructureND(this, permutation) + +public class PermutedMutableStructureND( + public val origin: MutableStructureND, + override val shape: Shape = origin.shape, + public val permutation: (IntArray) -> IntArray, +) : MutableStructureND { + + + @OptIn(PerformancePitfall::class) + override fun set(index: IntArray, value: T) { + origin[permutation(index)] = value + } + + @OptIn(PerformancePitfall::class) + override fun get(index: IntArray): T { + return origin[permutation(index)] + } +} + +public fun MutableStructureND.permute( + newShape: Shape = shape, + permutation: (IntArray) -> IntArray, +): PermutedMutableStructureND = PermutedMutableStructureND(this, newShape, permutation) \ No newline at end of file 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 index fc0b4b6ea..8dd17ab32 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt @@ -5,21 +5,88 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.UnsafeKMathAPI +import kotlin.jvm.JvmInline + +/** + * A read-only ND shape + */ +@JvmInline +public value class Shape(@PublishedApi internal val array: IntArray) { + public val size: Int get() = array.size + public operator fun get(index: Int): Int = array[index] + override fun toString(): String = array.contentToString() +} + +public inline fun Shape.forEach(block: (value: Int) -> Unit): Unit = array.forEach(block) + +public inline fun Shape.forEachIndexed(block: (index: Int, value: Int) -> Unit): Unit = array.forEachIndexed(block) + +public infix fun Shape.contentEquals(other: Shape): Boolean = array.contentEquals(other.array) + +public fun Shape.contentHashCode(): Int = array.contentHashCode() + +public val Shape.indices: IntRange get() = array.indices +public val Shape.linearSize: Int get() = array.reduce(Int::times) + +public fun Shape.slice(range: IntRange): Shape = Shape(array.sliceArray(range)) + +public fun Shape.last(): Int = array.last() + +/** + * A shape including last [n] dimensions of this shape + */ +public fun Shape.last(n: Int): Shape = Shape(array.copyOfRange(size - n, size)) + +public fun Shape.first(): Int = array.first() + +/** + * A shape including first [n] dimensions of this shape + */ +public fun Shape.first(n: Int): Shape = Shape(array.copyOfRange(0, n)) + +public operator fun Shape.plus(add: IntArray): Shape = Shape(array + add) + +public operator fun Shape.plus(add: Shape): Shape = Shape(array + add.array) + +public fun Shape.isEmpty(): Boolean = size == 0 +public fun Shape.isNotEmpty(): Boolean = size > 0 + +public fun Shape.transposed(i: Int, j: Int): Shape = Shape(array.copyOf().apply { + val ith = get(i) + val jth = get(j) + set(i, jth) + set(j, ith) +}) + +public operator fun Shape.component1(): Int = get(0) +public operator fun Shape.component2(): Int = get(1) +public operator fun Shape.component3(): Int = get(2) + +/** + * Convert to array with protective copy + */ +public fun Shape.toArray(): IntArray = array.copyOf() + +@UnsafeKMathAPI +public fun Shape.asArray(): IntArray = array + +public fun Shape.asList(): List = array.asList() + + /** * 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 ShapeMismatchException(public val expected: Shape, public val actual: Shape) : + RuntimeException("Shape $actual doesn't fit in expected shape ${expected}.") public class IndexOutOfShapeException(public val shape: Shape, public val index: IntArray) : - RuntimeException("Index ${index.contentToString()} is out of shape ${shape.contentToString()}") + RuntimeException("Index ${index.contentToString()} is out of shape ${shape}") -public typealias Shape = IntArray - -public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(shapeFirst, *shapeRest) +public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = Shape(intArrayOf(shapeFirst, *shapeRest)) public interface WithShape { public val shape: Shape @@ -28,8 +95,8 @@ public interface WithShape { } internal fun requireIndexInShape(index: IntArray, shape: Shape) { - if (index.size != shape.size) throw IndexOutOfShapeException(index, shape) + if (index.size != shape.size) throw IndexOutOfShapeException(shape, index) shape.forEachIndexed { axis, axisShape -> - if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(index, shape) + if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(shape, index) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index 4b31e3fc5..d2ea302fd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -49,10 +49,10 @@ public abstract class Strides : ShapeIndexer { /** * Array strides */ - public abstract val strides: IntArray + internal abstract val strides: IntArray public override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") + if (value !in 0 until shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0, ${this.shape[i]})") value * strides[i] }.sum() @@ -63,15 +63,12 @@ public abstract class Strides : ShapeIndexer { */ public override fun asSequence(): Sequence = (0 until linearSize).asSequence().map(::index) - public companion object{ - public fun linearSizeOf(shape: IntArray): Int = shape.reduce(Int::times) - } } /** * Column-first [Strides]. Columns are represented as continuous arrays */ -public class ColumnStrides(override val shape: IntArray) : Strides() { +public class ColumnStrides(override val shape: Shape) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -121,7 +118,7 @@ public class ColumnStrides(override val shape: IntArray) : Strides() { * * @param shape the shape of the tensor. */ -public class RowStrides(override val shape: IntArray) : Strides() { +public class RowStrides(override val shape: Shape) : Strides() { override val strides: IntArray by lazy { val nDim = shape.size @@ -151,7 +148,7 @@ public class RowStrides(override val shape: IntArray) : Strides() { return res } - override val linearSize: Int get() = linearSizeOf(shape) + override val linearSize: Int get() = shape.linearSize override fun equals(other: Any?): Boolean { if (this === other) return true @@ -166,9 +163,9 @@ public class RowStrides(override val shape: IntArray) : Strides() { } @ThreadLocal -private val defaultStridesCache = HashMap() +private val defaultStridesCache = HashMap() /** * Cached builder for default strides */ -public fun Strides(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of file +public fun Strides(shape: Shape): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(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 249b6801d..d34c722a1 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 @@ -30,5 +30,5 @@ public class ShortRingND( public inline fun ShortRing.withNdAlgebra(vararg shape: Int, action: ShortRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ShortRingND(shape).run(action) + return ShortRingND(Shape(shape)).run(action) } 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 2a258a7f4..51a3d7fd0 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 @@ -18,6 +18,7 @@ import kotlin.jvm.JvmInline public interface Structure1D : StructureND, Buffer { override val dimension: Int get() = 1 + @PerformancePitfall override operator fun get(index: IntArray): T { require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" } return get(index[0]) @@ -32,6 +33,8 @@ public interface Structure1D : StructureND, Buffer { * A mutable structure that is guaranteed to be one-dimensional */ public interface MutableStructure1D : Structure1D, MutableStructureND, MutableBuffer { + + @PerformancePitfall override operator fun set(index: IntArray, value: T) { require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" } set(index[0], value) @@ -43,9 +46,10 @@ public interface MutableStructure1D : Structure1D, MutableStructureND, */ @JvmInline private value class Structure1DWrapper(val structure: StructureND) : Structure1D { - override val shape: IntArray get() = structure.shape + override val shape: Shape get() = structure.shape override val size: Int get() = structure.shape[0] + @PerformancePitfall override operator fun get(index: Int): T = structure[index] @PerformancePitfall @@ -56,13 +60,16 @@ private value class Structure1DWrapper(val structure: StructureND) : S * A 1D wrapper for a mutable nd-structure */ private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { - override val shape: IntArray get() = structure.shape + override val shape: Shape get() = structure.shape override val size: Int get() = structure.shape[0] @PerformancePitfall override fun elements(): Sequence> = structure.elements() + @PerformancePitfall override fun get(index: Int): T = structure[index] + + @PerformancePitfall override fun set(index: Int, value: T) { structure[intArrayOf(index)] = value } @@ -83,7 +90,7 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) */ @JvmInline private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { - override val shape: IntArray get() = intArrayOf(buffer.size) + override val shape: Shape get() = Shape(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall @@ -95,7 +102,7 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D< } internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { - override val shape: IntArray get() = intArrayOf(buffer.size) + override val shape: Shape get() = Shape(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall 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 2822a74d4..d10c43c25 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 @@ -29,7 +29,7 @@ public interface Structure2D : StructureND { */ public val colNum: Int - override val shape: IntArray get() = intArrayOf(rowNum, colNum) + override val shape: Shape get() = Shape(rowNum, colNum) /** * The buffer of rows of this structure. It gets elements from the structure dynamically. @@ -54,6 +54,7 @@ public interface Structure2D : StructureND { */ public operator fun get(i: Int, j: Int): T + @PerformancePitfall override operator fun get(index: IntArray): T { require(index.size == 2) { "Index dimension mismatch. Expected 2 but found ${index.size}" } return get(index[0], index[1]) @@ -106,6 +107,7 @@ private value class Structure2DWrapper(val structure: StructureND) : S override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] + @PerformancePitfall override operator fun get(i: Int, j: Int): T = structure[i, j] override fun getFeature(type: KClass): F? = structure.getFeature(type) @@ -123,12 +125,15 @@ private class MutableStructure2DWrapper(val structure: MutableStructureND) override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] + @PerformancePitfall override operator fun get(i: Int, j: Int): T = structure[i, j] + @PerformancePitfall override fun set(index: IntArray, value: T) { structure[index] = value } + @PerformancePitfall override operator fun set(i: Int, j: Int, value: T) { structure[intArrayOf(i, j)] = value } 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 4e1cc1ff4..baea5da15 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 @@ -46,6 +46,7 @@ public interface StructureND : Featured, WithShape { * @param index the indices. * @return the value. */ + @PerformancePitfall public operator fun get(index: IntArray): T /** @@ -97,6 +98,7 @@ public interface StructureND : Featured, WithShape { /** * Debug output to string */ + @OptIn(PerformancePitfall::class) public fun toString(structure: StructureND<*>): String { val bufferRepr: String = when (structure.shape.size) { 1 -> (0 until structure.shape[0]).map { structure[it] } @@ -116,7 +118,7 @@ public interface StructureND : Featured, WithShape { } val className = structure::class.simpleName ?: "StructureND" - return "$className(shape=${structure.shape.contentToString()}, buffer=$bufferRepr)" + return "$className(shape=${structure.shape}, buffer=$bufferRepr)" } /** @@ -145,13 +147,13 @@ public interface StructureND : Featured, WithShape { ): BufferND = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) public fun buffered( - shape: IntArray, + shape: Shape, bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = buffered(ColumnStrides(shape), bufferFactory, initializer) public inline fun auto( - shape: IntArray, + shape: Shape, crossinline initializer: (IntArray) -> T, ): BufferND = auto(ColumnStrides(shape), initializer) @@ -160,13 +162,13 @@ public interface StructureND : Featured, WithShape { vararg shape: Int, crossinline initializer: (IntArray) -> T, ): BufferND = - auto(ColumnStrides(shape), initializer) + auto(ColumnStrides(Shape(shape)), initializer) public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): BufferND = auto(type, ColumnStrides(shape), initializer) + ): BufferND = auto(type, ColumnStrides(Shape(shape)), initializer) } } @@ -214,8 +216,13 @@ public fun > LinearSpace>.contentEquals( * @param index the indices. * @return the value. */ +@PerformancePitfall public operator fun StructureND.get(vararg index: Int): T = get(index) +public operator fun StructureND.get(vararg index: Int): Double = getDouble(index) + +public operator fun StructureND.get(vararg index: Int): Int = getInt(index) + //@UnstableKMathAPI //public inline fun StructureND<*>.getFeature(): T? = getFeature(T::class) @@ -229,12 +236,14 @@ public interface MutableStructureND : StructureND { * @param index the indices. * @param value the value. */ + @PerformancePitfall public operator fun set(index: IntArray, value: T) } /** * Set value at specified indices */ +@PerformancePitfall 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 index 579a0d7c8..e5edeef7f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI public open class VirtualStructureND( override val shape: Shape, public val producer: (IntArray) -> T, ) : StructureND { + + @PerformancePitfall override fun get(index: IntArray): T { requireIndexInShape(index, shape) return producer(index) 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 index 5814e2f9c..424081738 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt @@ -5,6 +5,9 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall + +@OptIn(PerformancePitfall::class) 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 -> @@ -19,6 +22,7 @@ public fun StructureND.roll(axis: Int, step: Int = 1): StructureND { } } +@OptIn(PerformancePitfall::class) 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})" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt new file mode 100644 index 000000000..f50233ecc --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2018-2022 KMath 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.PerformancePitfall + +public interface StructureNDOfDouble : StructureND { + /** + * Guaranteed non-blocking access to content + */ + public fun getDouble(index: IntArray): Double +} + +/** + * Optimized method to access primitive without boxing if possible + */ +@OptIn(PerformancePitfall::class) +public fun StructureND.getDouble(index: IntArray): Double = + if (this is StructureNDOfDouble) getDouble(index) else get(index) + +public interface MutableStructureNDOfDouble : StructureNDOfDouble, MutableStructureND { + /** + * Guaranteed non-blocking access to content + */ + public fun setDouble(index: IntArray, value: Double) +} + +@OptIn(PerformancePitfall::class) +public fun MutableStructureND.getDouble(index: IntArray): Double = + if (this is StructureNDOfDouble) getDouble(index) else get(index) + + +public interface StructureNDOfInt : StructureND { + /** + * Guaranteed non-blocking access to content + */ + public fun getInt(index: IntArray): Int +} + +@OptIn(PerformancePitfall::class) +public fun StructureND.getInt(index: IntArray): Int = + if (this is StructureNDOfInt) getInt(index) else get(index) 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 f61a0a623..b1b6fba9f 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 @@ -5,10 +5,7 @@ package space.kscience.kmath.structures -import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.as2D +import space.kscience.kmath.nd.* /** * A context that allows to operate on a [MutableBuffer] as on 2d array @@ -31,7 +28,7 @@ internal class BufferAccessor2D( //TODO optimize wrapper fun MutableBuffer.collect(): Structure2D = StructureND.buffered( - ColumnStrides(intArrayOf(rowNum, colNum)), + ColumnStrides(Shape(rowNum, colNum)), factory ) { (i, j) -> get(i, j) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt index eac4f17e1..7044eb930 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt @@ -10,7 +10,7 @@ import kotlin.test.Test class StridesTest { @Test fun checkRowBasedStrides() { - val strides = RowStrides(intArrayOf(3, 3)) + val strides = RowStrides(Shape(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ @@ -24,7 +24,7 @@ class StridesTest { @Test fun checkColumnBasedStrides() { - val strides = ColumnStrides(intArrayOf(3, 3)) + val strides = ColumnStrides(Shape(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ 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 a54af571e..147488273 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 @@ -88,7 +88,7 @@ class NumberNDFieldTest { @Test fun testInternalContext() { algebra { - (DoubleField.ndAlgebra(*array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } } + (DoubleField.ndAlgebra(array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } } } } } 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 c217c3a26..97e27df96 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 @@ -9,11 +9,12 @@ import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND public class LazyStructureND( public val scope: CoroutineScope, - override val shape: IntArray, + override val shape: Shape, public val function: suspend (IntArray) -> T, ) : StructureND { private val cache: MutableMap> = HashMap() @@ -23,6 +24,7 @@ public class LazyStructureND( } public suspend fun await(index: IntArray): T = async(index).await() + @PerformancePitfall override operator fun get(index: IntArray): T = runBlocking { async(index).await() } @OptIn(PerformancePitfall::class) 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 b93114804..30c84d848 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.dimensions import space.kscience.kmath.linear.* +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring @@ -47,7 +48,7 @@ public interface DMatrix : Structure2D { public value class DMatrixWrapper( private val structure: Structure2D, ) : DMatrix { - override val shape: IntArray get() = structure.shape + override val shape: Shape get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] override operator fun get(i: Int, j: Int): T = structure[i, j] 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 e3bff8987..d1ae80ef9 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 @@ -15,6 +15,7 @@ import space.kscience.kmath.linear.* import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.toArray import space.kscience.kmath.operations.algebra import kotlin.random.Random import kotlin.random.asJavaRandom @@ -52,7 +53,7 @@ internal class EjmlMatrixTest { fun shape() { val m = randomMatrix val w = EjmlDoubleMatrix(m) - assertContentEquals(intArrayOf(m.numRows, m.numCols), w.shape) + assertContentEquals(intArrayOf(m.numRows, m.numCols), w.shape.toArray()) } @OptIn(UnstableKMathAPI::class) 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 1c9f00838..06320c8d9 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.FieldOpsND import space.kscience.kmath.nd.Shape @@ -24,6 +25,7 @@ public class HistogramND, D : Domain, V : Any>( internal val values: StructureND, ) : Histogram> { + @OptIn(PerformancePitfall::class) override fun get(point: Point): DomainBin? { val index = group.getIndexOrNull(point) ?: return null return group.produceBin(index, values[index]) @@ -31,6 +33,7 @@ public class HistogramND, D : Domain, V : Any>( override val dimension: Int get() = group.shape.size + @OptIn(PerformancePitfall::class) override val bins: Iterable> get() = ColumnStrides(group.shape).asSequence().map { group.produceBin(it, values[it]) 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 36e994bcf..cf8b59087 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 @@ -9,11 +9,10 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.HyperSquareDomain import space.kscience.kmath.linear.Point +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.operations.Field -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.* import kotlin.math.floor @@ -40,7 +39,7 @@ public class UniformHistogramGroupND>( public val dimension: Int get() = lower.size - override val shape: IntArray = IntArray(binNums.size) { binNums[it] + 2 } + override val shape: Shape = Shape(IntArray(binNums.size) { binNums[it] + 2 }) private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } @@ -83,8 +82,12 @@ public class UniformHistogramGroupND>( } - override fun produce(builder: HistogramBuilder.() -> Unit): HistogramND { - val ndCounter = StructureND.buffered(shape) { Counter.of(valueAlgebraND.elementAlgebra) } + @OptIn(PerformancePitfall::class) + override fun produce( + builder: HistogramBuilder.() -> Unit, + ): HistogramND { + val ndCounter: BufferND> = + StructureND.buffered(shape) { Counter.of(valueAlgebraND.elementAlgebra) } val hBuilder = object : HistogramBuilder { override val defaultValue: V get() = valueAlgebraND.elementAlgebra.one @@ -94,7 +97,8 @@ public class UniformHistogramGroupND>( } } hBuilder.apply(builder) - val values: BufferND = ndCounter.mapToBuffer(valueBufferFactory) { it.value } + val values: BufferND = BufferND(ndCounter.indices, ndCounter.buffer.map(valueBufferFactory) { it.value }) + return HistogramND(this, values) } 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 7e11c9a2f..64cc4f203 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.operations.invoke @@ -50,6 +51,7 @@ internal class MultivariateHistogramTest { assertEquals(n, histogram.bins.sumOf { it.binValue.toInt() }) } + @OptIn(PerformancePitfall::class) @Test fun testHistogramAlgebra() { Histogram.uniformDoubleNDFromRanges( 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 index 38d61e982..88c004c7b 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -13,14 +13,16 @@ import kotlin.jvm.JvmInline @JvmInline public value class MultikTensor(public val array: MutableMultiArray) : Tensor { - override val shape: Shape get() = array.shape + override val shape: Shape get() = Shape(array.shape) + @PerformancePitfall override fun get(index: IntArray): T = array[index] @PerformancePitfall override fun elements(): Sequence> = array.multiIndices.iterator().asSequence().map { it to get(it) } + @PerformancePitfall override fun set(index: IntArray, value: T) { array[index] = value } diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index dd0249fbc..99cbc3193 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -14,6 +14,7 @@ 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.misc.UnsafeKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.tensors.api.Tensor @@ -30,21 +31,22 @@ public abstract class MultikTensorAlgebra>( protected val multikLinAl: LinAlg = multikEngine.getLinAlg() protected val multikStat: Statistics = multikEngine.getStatistics() + @OptIn(UnsafeKMathAPI::class) override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { val strides = ColumnStrides(shape) val memoryView = initMemoryView(strides.linearSize, type) strides.asSequence().forEachIndexed { linearIndex, tensorIndex -> memoryView[linearIndex] = elementAlgebra.initializer(tensorIndex) } - return MultikTensor(NDArray(memoryView, shape = shape, dim = DN(shape.size))) + return MultikTensor(NDArray(memoryView, shape = shape.asArray(), dim = DN(shape.size))) } - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override fun StructureND.map(transform: A.(T) -> T): MultikTensor = if (this is MultikTensor) { val data = initMemoryView(array.size, type) var count = 0 for (el in array) data[count++] = elementAlgebra.transform(el) - NDArray(data, shape = shape, dim = array.dim).wrap() + NDArray(data, shape = shape.asArray(), dim = array.dim).wrap() } else { structureND(shape) { index -> transform(get(index)) @@ -75,6 +77,7 @@ public abstract class MultikTensorAlgebra>( /** * Transform a structure element-by element in place. */ + @OptIn(PerformancePitfall::class) public inline fun MutableStructureND.mapIndexedInPlace(operation: (index: IntArray, t: T) -> T): Unit { if (this is MultikTensor) { array.multiIndices.iterator().forEach { @@ -106,10 +109,11 @@ public abstract class MultikTensorAlgebra>( * Convert a tensor to [MultikTensor] if necessary. If tensor is converted, changes on the resulting tensor * are not reflected back onto the source */ + @OptIn(UnsafeKMathAPI::class, PerformancePitfall::class) public fun StructureND.asMultik(): MultikTensor = if (this is MultikTensor) { this } else { - val res = mk.zeros(shape, type).asDNArray() + val res = mk.zeros(shape.asArray(), type).asDNArray() for (index in res.multiIndices) { res[index] = this[index] } @@ -118,7 +122,8 @@ public abstract class MultikTensorAlgebra>( public fun MutableMultiArray.wrap(): MultikTensor = MultikTensor(this.asDNArray()) - override fun StructureND.valueOrNull(): T? = if (shape contentEquals intArrayOf(1)) { + @OptIn(PerformancePitfall::class) + override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) { get(intArrayOf(0)) } else null @@ -139,6 +144,7 @@ public abstract class MultikTensorAlgebra>( } } + @OptIn(PerformancePitfall::class) override fun Tensor.plusAssign(arg: StructureND) { if (this is MultikTensor) { array.plusAssign(arg.asMultik().array) @@ -163,6 +169,7 @@ public abstract class MultikTensorAlgebra>( } } + @OptIn(PerformancePitfall::class) override fun Tensor.minusAssign(arg: StructureND) { if (this is MultikTensor) { array.minusAssign(arg.asMultik().array) @@ -188,6 +195,7 @@ public abstract class MultikTensorAlgebra>( } } + @OptIn(PerformancePitfall::class) override fun Tensor.timesAssign(arg: StructureND) { if (this is MultikTensor) { array.timesAssign(arg.asMultik().array) @@ -201,13 +209,13 @@ public abstract class MultikTensorAlgebra>( override fun Tensor.getTensor(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() - override fun Tensor.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() + override fun StructureND.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() - override fun Tensor.view(shape: IntArray): MultikTensor { - require(shape.all { it > 0 }) - require(shape.fold(1, Int::times) == this.shape.size) { + override fun Tensor.view(shape: Shape): MultikTensor { + require(shape.asList().all { it > 0 }) + require(shape.linearSize == this.shape.size) { "Cannot reshape array of size ${this.shape.size} into a new shape ${ - shape.joinToString( + shape.asList().joinToString( prefix = "(", postfix = ")" ) @@ -215,10 +223,11 @@ public abstract class MultikTensorAlgebra>( } val mt = asMultik().array - return if (mt.shape.contentEquals(shape)) { + return if (Shape(mt.shape).contentEquals(shape)) { mt } else { - NDArray(mt.data, mt.offset, shape, dim = DN(shape.size), base = mt.base ?: mt) + @OptIn(UnsafeKMathAPI::class) + NDArray(mt.data, mt.offset, shape.asArray(), dim = DN(shape.size), base = mt.base ?: mt) }.wrap() } @@ -241,7 +250,7 @@ public abstract class MultikTensorAlgebra>( TODO("Not implemented for broadcasting") } - override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): MultikTensor { + override fun diagonalEmbedding(diagonalEntries: StructureND, offset: Int, dim1: Int, dim2: Int): MultikTensor { TODO("Diagonal embedding not implemented") } @@ -284,8 +293,9 @@ public abstract class MultikDivisionTensorAlgebra>( multikEngine: Engine, ) : MultikTensorAlgebra(multikEngine), TensorPartialDivisionAlgebra where T : Number, T : Comparable { + @OptIn(UnsafeKMathAPI::class) override fun T.div(arg: StructureND): MultikTensor = - Multik.ones(arg.shape, type).apply { divAssign(arg.asMultik().array) }.wrap() + Multik.ones(arg.shape.asArray(), type).apply { divAssign(arg.asMultik().array) }.wrap() override fun StructureND.div(arg: T): MultikTensor = asMultik().array.div(arg).wrap() @@ -301,6 +311,7 @@ public abstract class MultikDivisionTensorAlgebra>( } } + @OptIn(PerformancePitfall::class) override fun Tensor.divAssign(arg: StructureND) { if (this is MultikTensor) { array.divAssign(arg.asMultik().array) diff --git a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index 392532d8e..de54af732 100644 --- a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.default.DefaultEngine import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -28,8 +29,8 @@ internal class MultikNDTest { fun dotResult() { val dim = 100 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) val multikResult = with(multikAlgebra) { tensor1 dot tensor2 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 859773211..7654ec9ce 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 @@ -11,6 +11,7 @@ import org.nd4j.linalg.api.ops.impl.transforms.strict.ASinh import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnsafeKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -33,7 +34,8 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.ndArray: INDArray override fun structureND(shape: Shape, initializer: C.(IntArray) -> T): Nd4jArrayStructure { - val struct = Nd4j.create(*shape)!!.wrap() + @OptIn(UnsafeKMathAPI::class) + val struct: Nd4jArrayStructure = Nd4j.create(*shape.asArray())!!.wrap() struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) } return struct } @@ -45,23 +47,23 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.mapIndexed( transform: C.(index: IntArray, T) -> T, ): Nd4jArrayStructure { - val new = Nd4j.create(*shape).wrap() + val new = Nd4j.create(*shape.asArray()).wrap() new.indicesIterator().forEach { idx -> new[idx] = elementAlgebra.transform(idx, this[idx]) } return new } - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override fun zip( left: StructureND, right: StructureND, transform: C.(T, T) -> T, ): Nd4jArrayStructure { require(left.shape.contentEquals(right.shape)) { "Can't zip tow structures of shape ${left.shape} and ${right.shape}" } - val new = Nd4j.create(*left.shape).wrap() + val new = Nd4j.create(*left.shape.asArray()).wrap() new.indicesIterator().forEach { idx -> new[idx] = elementAlgebra.transform(left[idx], right[idx]) } return new } @@ -192,11 +194,11 @@ public open class DoubleNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps = asDoubleStructure() - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override val StructureND.ndArray: INDArray get() = when (this) { is Nd4jArrayStructure -> ndArray - else -> Nd4j.zeros(*shape).also { + else -> Nd4j.zeros(*shape.asArray()).also { elements().forEach { (idx, value) -> it.putScalar(idx, value) } } } @@ -225,7 +227,7 @@ public val DoubleField.nd4j: DoubleNd4jArrayFieldOps get() = DoubleNd4jArrayFiel public class DoubleNd4jArrayField(override val shape: Shape) : DoubleNd4jArrayFieldOps(), FieldND public fun DoubleField.nd4j(shapeFirst: Int, vararg shapeRest: Int): DoubleNd4jArrayField = - DoubleNd4jArrayField(intArrayOf(shapeFirst, * shapeRest)) + DoubleNd4jArrayField(Shape(shapeFirst, * shapeRest)) /** @@ -236,11 +238,11 @@ public open class FloatNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps = asFloatStructure() - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override val StructureND.ndArray: INDArray get() = when (this) { is Nd4jArrayStructure -> ndArray - else -> Nd4j.zeros(*shape).also { + else -> Nd4j.zeros(*shape.asArray()).also { elements().forEach { (idx, value) -> it.putScalar(idx, value) } } } @@ -274,7 +276,7 @@ public class FloatNd4jArrayField(override val shape: Shape) : FloatNd4jArrayFiel public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps public fun FloatField.nd4j(shapeFirst: Int, vararg shapeRest: Int): FloatNd4jArrayField = - FloatNd4jArrayField(intArrayOf(shapeFirst, * shapeRest)) + FloatNd4jArrayField(Shape(shapeFirst, * shapeRest)) /** * Represents [RingND] over [Nd4jArrayIntStructure]. @@ -284,11 +286,11 @@ public open class IntNd4jArrayRingOps : Nd4jArrayRingOps { override fun INDArray.wrap(): Nd4jArrayStructure = asIntStructure() - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override val StructureND.ndArray: INDArray get() = when (this) { is Nd4jArrayStructure -> ndArray - else -> Nd4j.zeros(*shape).also { + else -> Nd4j.zeros(*shape.asArray()).also { elements().forEach { (idx, value) -> it.putScalar(idx, value) } } } @@ -313,4 +315,4 @@ public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND public fun IntRing.nd4j(shapeFirst: Int, vararg shapeRest: Int): IntNd4jArrayRing = - IntNd4jArrayRing(intArrayOf(shapeFirst, * shapeRest)) \ No newline at end of file + IntNd4jArrayRing(Shape(shapeFirst, * shapeRest)) \ No newline at end of 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 0a7d15e20..60c865a02 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 @@ -7,8 +7,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.MutableStructureND -import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.* /** * Represents a [StructureND] wrapping an [INDArray] object. @@ -22,7 +21,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { */ public abstract val ndArray: INDArray - override val shape: IntArray get() = ndArray.shape().toIntArray() + override val shape: Shape get() = Shape(ndArray.shape().toIntArray()) internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() @@ -31,20 +30,31 @@ public sealed class Nd4jArrayStructure : MutableStructureND { override fun elements(): Sequence> = Sequence(::elementsIterator) } -private data class Nd4jArrayIntStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { +public data class Nd4jArrayIntStructure(override val ndArray: INDArray) : Nd4jArrayStructure(), StructureNDOfInt { override fun elementsIterator(): Iterator> = ndArray.intIterator() + + @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Int = ndArray.getInt(*index) + + override fun getInt(index: IntArray): Int = ndArray.getInt(*index) + + @OptIn(PerformancePitfall::class) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } } /** * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asIntStructure(): Nd4jArrayStructure = Nd4jArrayIntStructure(this) +public fun INDArray.asIntStructure(): Nd4jArrayIntStructure = Nd4jArrayIntStructure(this) -private data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { +public data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd4jArrayStructure(), StructureNDOfDouble { override fun elementsIterator(): Iterator> = ndArray.realIterator() + @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Double = ndArray.getDouble(*index) + + override fun getDouble(index: IntArray): Double = ndArray.getDouble(*index) + + @OptIn(PerformancePitfall::class) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } } @@ -53,9 +63,12 @@ private data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd */ public fun INDArray.asDoubleStructure(): Nd4jArrayStructure = Nd4jArrayDoubleStructure(this) -private data class Nd4jArrayFloatStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { +public data class Nd4jArrayFloatStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.floatIterator() + @PerformancePitfall override fun get(index: IntArray): Float = ndArray.getFloat(*index) + + @PerformancePitfall override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } } 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 b0fce8dcf..d505b3c0e 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 @@ -13,9 +13,8 @@ import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.factory.ops.NDBase import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape -import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra @@ -96,7 +95,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun StructureND.unaryMinus(): Nd4jArrayStructure = ndArray.neg().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.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,7 +107,9 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun StructureND.max(dim: Int, keepDim: Boolean): Nd4jArrayStructure = ndArray.max(keepDim, dim).wrap() - override fun Tensor.view(shape: IntArray): Nd4jArrayStructure = ndArray.reshape(shape).wrap() + @OptIn(UnsafeKMathAPI::class) + override fun Tensor.view(shape: Shape): Nd4jArrayStructure = ndArray.reshape(shape.asArray()).wrap() + override fun Tensor.viewAs(other: StructureND): Nd4jArrayStructure = view(other.shape) override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = @@ -176,8 +177,9 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { override fun INDArray.wrap(): Nd4jArrayStructure = asDoubleStructure() + @OptIn(UnsafeKMathAPI::class) override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { - val array: INDArray = Nd4j.zeros(*shape) + val array: INDArray = Nd4j.zeros(*shape.asArray()) val indices = ColumnStrides(shape) indices.asSequence().forEach { index -> array.putScalar(index, elementAlgebra.initializer(index)) @@ -186,21 +188,21 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { } - @OptIn(PerformancePitfall::class) + @OptIn(PerformancePitfall::class, UnsafeKMathAPI::class) override val StructureND.ndArray: INDArray get() = when (this) { is Nd4jArrayStructure -> ndArray - else -> Nd4j.zeros(*shape).also { + else -> Nd4j.zeros(*shape.asArray()).also { elements().forEach { (idx, value) -> it.putScalar(idx, value) } } } override fun StructureND.valueOrNull(): Double? = - if (shape contentEquals intArrayOf(1)) ndArray.getDouble(0) else null + if (shape contentEquals Shape(1)) ndArray.getDouble(0) else null // TODO rewrite override fun diagonalEmbedding( - diagonalEntries: Tensor, + diagonalEntries: StructureND, offset: Int, dim1: Int, dim2: Int, 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 d1ad746fe..25c3fe23f 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.asList import space.kscience.kmath.nd.get import kotlin.test.Test import kotlin.test.assertEquals @@ -27,7 +28,7 @@ internal class Nd4jArrayStructureTest { fun testShape() { val nd = Nd4j.rand(10, 2, 3, 6) ?: fail() val struct = nd.asDoubleStructure() - assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList()) + assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.asList()) } @Test 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 953076680..674485fd1 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 @@ -28,6 +28,8 @@ public class DoubleTensorFlowOutput( } +internal fun Shape.toLongArray(): LongArray = LongArray(size) { get(it).toLong() } + public class DoubleTensorFlowAlgebra internal constructor( graph: Graph, ) : TensorFlowAlgebra(graph), PowerOperations> { 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 74fcf2d7d..a1e0335f8 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 @@ -18,9 +18,12 @@ import org.tensorflow.types.TInt32 import org.tensorflow.types.family.TNumber import org.tensorflow.types.family.TType import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnsafeKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.asArray +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.Ring import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra @@ -38,7 +41,7 @@ public sealed interface TensorFlowTensor : Tensor */ @JvmInline public value class TensorFlowArray(public val tensor: NdArray) : Tensor { - override val shape: Shape get() = tensor.shape().asArray().toIntArray() + override val shape: Shape get() = Shape(tensor.shape().asArray().toIntArray()) override fun get(index: IntArray): T = tensor.getObject(*index.toLongArray()) @@ -62,7 +65,7 @@ public abstract class TensorFlowOutput( public var output: Output = output internal set - override val shape: Shape get() = output.shape().asArray().toIntArray() + override val shape: Shape get() = Shape(output.shape().asArray().toIntArray()) protected abstract fun org.tensorflow.Tensor.actualizeTensor(): NdArray @@ -96,8 +99,8 @@ public abstract class TensorFlowAlgebra> internal c protected abstract fun const(value: T): Constant - override fun StructureND.valueOrNull(): T? = if (shape contentEquals intArrayOf(1)) - get(Shape(0)) else null + override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) + get(intArrayOf(0)) else null /** * Perform binary lazy operation on tensor. Both arguments are implicitly converted @@ -188,12 +191,13 @@ public abstract class TensorFlowAlgebra> internal c StridedSliceHelper.stridedSlice(ops.scope(), it, Indices.at(i.toLong())) } - override fun Tensor.transposed(i: Int, j: Int): Tensor = operate { + override fun StructureND.transposed(i: Int, j: Int): Tensor = operate { ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } - override fun Tensor.view(shape: IntArray): Tensor = operate { - ops.reshape(it, ops.constant(shape)) + override fun Tensor.view(shape: Shape): Tensor = operate { + @OptIn(UnsafeKMathAPI::class) + ops.reshape(it, ops.constant(shape.asArray())) } override fun Tensor.viewAs(other: StructureND): Tensor = operate(other) { l, r -> @@ -208,7 +212,7 @@ public abstract class TensorFlowAlgebra> internal c } override fun diagonalEmbedding( - diagonalEntries: Tensor, + diagonalEntries: StructureND, offset: Int, dim1: Int, dim2: Int, 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 a35556be1..44a594299 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField @@ -31,8 +32,8 @@ class DoubleTensorFlowOps { fun dot(){ val dim = 1000 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) DoubleField.produceWithTF { tensor1 dot tensor2 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 07dfd1597..e15fbb3a6 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 @@ -21,7 +21,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * * @return the determinant. */ - public fun StructureND.det(): Tensor + public fun StructureND.det(): StructureND /** * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. @@ -31,7 +31,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * * @return the multiplicative inverse of a matrix. */ - public fun StructureND.inv(): Tensor + public fun StructureND.inv(): StructureND /** * Cholesky decomposition. @@ -47,7 +47,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return the batch of `L` matrices. */ - public fun StructureND.cholesky(): Tensor + public fun StructureND.cholesky(): StructureND /** * QR decomposition. @@ -61,7 +61,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return pair of `Q` and `R` tensors. */ - public fun StructureND.qr(): Pair, Tensor> + public fun StructureND.qr(): Pair, StructureND> /** * LUP decomposition @@ -75,7 +75,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return triple of P, L and U tensors */ - public fun StructureND.lu(): Triple, Tensor, Tensor> + public fun StructureND.lu(): Triple, StructureND, StructureND> /** * Singular Value Decomposition. @@ -91,7 +91,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return triple `Triple(U, S, V)`. */ - public fun StructureND.svd(): Triple, Tensor, Tensor> + public fun StructureND.svd(): Triple, StructureND, StructureND> /** * Returns eigenvalues and eigenvectors of a real symmetric matrix `input` or a batch of real symmetric matrices, @@ -101,6 +101,6 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return a pair `eigenvalues to eigenvectors` */ - public fun StructureND.symEig(): Pair, Tensor> + public fun StructureND.symEig(): Pair, StructureND> } 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 70b985a54..ec5d6f5e6 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.RingOpsND +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Ring @@ -176,11 +177,13 @@ public interface TensorAlgebra> : RingOpsND { * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. * For more information: https://pytorch.org/docs/stable/generated/torch.transpose.html * + * If axis indices are negative, they are counted from shape end. + * * @param i the first dimension to be transposed * @param j the second dimension to be transposed * @return transposed tensor */ - public fun Tensor.transposed(i: Int = -2, j: Int = -1): Tensor + public fun StructureND.transposed(i: Int = shape.size - 2, j: Int = shape.size - 1): Tensor /** * Returns a new tensor with the same data as the self tensor but of a different shape. @@ -190,7 +193,7 @@ public interface TensorAlgebra> : RingOpsND { * @param shape the desired size * @return tensor with new shape */ - public fun Tensor.view(shape: IntArray): Tensor + public fun Tensor.view(shape: Shape): Tensor /** * View this tensor as the same size as [other]. @@ -248,7 +251,7 @@ public interface TensorAlgebra> : RingOpsND { * are filled by [diagonalEntries] */ public fun diagonalEmbedding( - diagonalEntries: Tensor, + diagonalEntries: StructureND, offset: Int = 0, dim1: Int = -2, dim2: Int = -1, 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 53f77195c..c4266c669 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.RowStrides +import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor @@ -15,7 +16,7 @@ import space.kscience.kmath.tensors.api.Tensor * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ public abstract class BufferedTensor( - override val shape: IntArray, + override val shape: Shape, ) : Tensor { public abstract val source: MutableBuffer 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 470b6070b..3dfea7f8a 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 @@ -7,10 +7,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.MutableStructureND -import space.kscience.kmath.nd.Shape -import space.kscience.kmath.nd.Strides +import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString import kotlin.jvm.JvmInline @@ -87,22 +84,30 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { * [DoubleTensor] always uses row-based strides */ public class DoubleTensor( - shape: IntArray, + shape: Shape, override val source: OffsetDoubleBuffer, -) : BufferedTensor(shape) { +) : BufferedTensor(shape), MutableStructureNDOfDouble { 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)) + public constructor(shape: Shape, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) - override fun get(index: IntArray): Double = this.source[indices.offset(index)] + @OptIn(PerformancePitfall::class) + override fun get(index: IntArray): Double = source[indices.offset(index)] + + @OptIn(PerformancePitfall::class) override fun set(index: IntArray, value: Double) { source[indices.offset(index)] = value } + override fun getDouble(index: IntArray): Double = get(index) + + override fun setDouble(index: IntArray, value: Double) { + set(index, value) + } override fun toString(): String = toPrettyString() } @@ -140,25 +145,26 @@ public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStru @PerformancePitfall override fun elements(): Sequence> = tensor.elements() + @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Double = tensor[index] override val shape: Shape get() = tensor.shape } public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D = DoubleTensor2D(this) -public fun DoubleTensor.asDoubleBuffer(): OffsetDoubleBuffer = if(shape.size == 1){ +public fun DoubleTensor.asDoubleBuffer(): OffsetDoubleBuffer = if (shape.size == 1) { source } else { - error("Only 1D tensors could be cast to 1D" ) + error("Only 1D tensors could be cast to 1D") } public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: DoubleTensor2D) -> Unit) { 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 matrixShape = Shape(shape[n - 2], shape[n - 1]) - val size = Strides.linearSizeOf(matrixShape) + val size = matrixShape.linearSize for (i in 0 until linearSize / matrixOffset) { val offset = i * matrixOffset val index = indices.index(offset).sliceArray(0 until (shape.size - 2)) 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 71e55a3b9..a022f31a6 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 @@ -11,7 +11,6 @@ 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.nd.Strides.Companion.linearSizeOf import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra @@ -93,7 +92,7 @@ public open class DoubleTensorAlgebra : override fun StructureND.valueOrNull(): Double? { val dt = asDoubleTensor() - return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + return if (dt.shape contentEquals Shape(1)) dt.source[0] else null } override fun StructureND.value(): Double = valueOrNull() @@ -106,7 +105,7 @@ public open class DoubleTensorAlgebra : * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: IntArray, array: DoubleArray): DoubleTensor { + public fun fromArray(shape: Shape, array: DoubleArray): DoubleTensor { checkNotEmptyShape(shape) checkEmptyDoubleBuffer(array) checkBufferShapeConsistency(shape, array) @@ -120,18 +119,18 @@ public open class DoubleTensorAlgebra : * @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: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( + override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( shape, RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) 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 lastShape = shape.last(shape.size - 1) + val newShape: Shape = if (lastShape.isNotEmpty()) lastShape else Shape(1) return DoubleTensor( newShape, - dt.source.view(newShape.reduce(Int::times) * i, linearSizeOf(newShape)) + dt.source.view(newShape.linearSize * i, newShape.linearSize) ) } @@ -142,9 +141,9 @@ public open class DoubleTensorAlgebra : * @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: Double, shape: IntArray): DoubleTensor { + public fun full(value: Double, shape: Shape): DoubleTensor { checkNotEmptyShape(shape) - val buffer = DoubleBuffer(shape.reduce(Int::times)) { value } + val buffer = DoubleBuffer(shape.linearSize) { value } return DoubleTensor(shape, buffer) } @@ -166,7 +165,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `0.0`, with the [shape] shape. */ - public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) + public fun zeros(shape: Shape): DoubleTensor = full(0.0, shape) /** * Returns a tensor filled with the scalar value `0.0`, with the same shape as a given array. @@ -181,7 +180,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `1.0`, with the [shape] shape. */ - public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) + public fun ones(shape: Shape): DoubleTensor = full(1.0, shape) /** * Returns a tensor filled with the scalar value `1.0`, with the same shape as a given array. @@ -197,7 +196,7 @@ public open class DoubleTensorAlgebra : * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. */ public fun eye(n: Int): DoubleTensor { - val shape = intArrayOf(n, n) + val shape = Shape(n, n) val buffer = DoubleBuffer(n * n) { 0.0 } val res = DoubleTensor(shape, buffer) for (i in 0 until n) { @@ -235,7 +234,7 @@ public open class DoubleTensorAlgebra : override fun Tensor.minusAssign(arg: StructureND) { checkShapesCompatible(this, arg) - mapIndexedInPlace { index, value -> value - arg[index] } + mapIndexedInPlace { index, value -> value - arg.getDouble(index) } } override fun Double.times(arg: StructureND): DoubleTensor = arg.map { this@times * it } @@ -270,32 +269,44 @@ public open class DoubleTensorAlgebra : override fun StructureND.unaryMinus(): DoubleTensor = map { -it } - 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 = dt.shape.copyOf() - resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } - - val resTensor = DoubleTensor(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] + override fun StructureND.transposed(i: Int, j: Int): Tensor { + val actualI = if (i >= 0) i else shape.size + i + val actualJ = if(j>=0) j else shape.size + j + return asDoubleTensor().permute( + shape.transposed(actualI, actualJ) + ) { originIndex -> + originIndex.copyOf().apply { + val ith = get(actualI) + val jth = get(actualJ) + set(actualI, jth) + set(actualJ, ith) + } } - return resTensor +// // 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 = dt.shape.copyOf() +// resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } +// +// val resTensor = DoubleTensor(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): DoubleTensor { + override fun Tensor.view(shape: Shape): DoubleTensor { checkView(asDoubleTensor(), shape) return DoubleTensor(shape, asDoubleTensor().source) } @@ -335,7 +346,7 @@ public open class DoubleTensorAlgebra : @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())) + return DoubleTensor(Shape(1), DoubleBuffer(times(other).sum())) } var penultimateDim = false @@ -347,7 +358,7 @@ public open class DoubleTensorAlgebra : if (shape.size == 1) { penultimateDim = true - newThis = newThis.view(intArrayOf(1) + shape) + newThis = newThis.view(Shape(1) + shape) } if (other.shape.size == 1) { @@ -367,8 +378,8 @@ public open class DoubleTensorAlgebra : "Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)" } - val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) - val resSize = resShape.reduce { acc, i -> acc * i } + val resShape = newThis.shape.slice(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) + val resSize = resShape.linearSize val resTensor = DoubleTensor(resShape, DoubleArray(resSize).asBuffer()) val resMatrices = resTensor.matrices @@ -385,9 +396,9 @@ public open class DoubleTensorAlgebra : // } return if (penultimateDim) { - resTensor.view(resTensor.shape.dropLast(2).toIntArray() + intArrayOf(resTensor.shape.last())) + resTensor.view(resTensor.shape.first(resTensor.shape.size - 2) + Shape(resTensor.shape.last())) } else if (lastDim) { - resTensor.view(resTensor.shape.dropLast(1).toIntArray()) + resTensor.view(resTensor.shape.first(resTensor.shape.size - 1)) } else { resTensor } @@ -399,7 +410,7 @@ public open class DoubleTensorAlgebra : } override fun diagonalEmbedding( - diagonalEntries: Tensor, + diagonalEntries: StructureND, offset: Int, dim1: Int, dim2: Int, @@ -423,11 +434,11 @@ public open class DoubleTensorAlgebra : lessDim = greaterDim.also { greaterDim = lessDim } } - val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + val resShape = diagonalEntries.shape.slice(0 until lessDim) + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + - diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + diagonalEntries.shape.slice(lessDim until greaterDim - 1) + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + - diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + diagonalEntries.shape.slice(greaterDim - 1 until n - 1) val resTensor: DoubleTensor = zeros(resShape) for (i in 0 until diagonalEntries.indices.linearSize) { @@ -495,8 +506,8 @@ public open class DoubleTensorAlgebra : * @return tensor of a given shape filled with numbers from the normal distribution * with `0.0` mean and `1.0` standard deviation. */ - public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = - DoubleTensor(shape, DoubleBuffer.randomNormals(shape.reduce(Int::times), seed)) + public fun randomNormal(shape: Shape, seed: Long = 0): DoubleTensor = + DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) /** * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions @@ -508,7 +519,7 @@ public open class DoubleTensorAlgebra : * with `0.0` mean and `1.0` standard deviation. */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = - DoubleTensor(shape, DoubleBuffer.randomNormals(shape.reduce(Int::times), seed)) + DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) /** * Concatenates a sequence of tensors with equal shapes along the first dimension. @@ -520,7 +531,7 @@ public open class DoubleTensorAlgebra : 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 resShape = Shape(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart) // .take(it.asDoubleTensor().linearSize) @@ -545,11 +556,11 @@ public open class DoubleTensorAlgebra : ): 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() + shape.first(dim) + intArrayOf(1) + shape.last(dimension - dim - 1) } else { - shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + shape.first(dim) + shape.last(dimension - dim - 1) } - val resNumElements = resShape.reduce(Int::times) + val resNumElements = resShape.linearSize val init = foldFunction(DoubleArray(1) { 0.0 }) val resTensor = DoubleTensor( resShape, @@ -573,11 +584,11 @@ public open class DoubleTensorAlgebra : ): 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() + shape.first(dim) + intArrayOf(1) + shape.last(dimension - dim - 1) } else { - shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + shape.first(dim) + shape.last(dimension - dim - 1) } - val resNumElements = resShape.reduce(Int::times) + val resNumElements = resShape.linearSize val init = foldFunction(DoubleArray(1) { 0.0 }) val resTensor = IntTensor( resShape, @@ -674,9 +685,9 @@ public open class DoubleTensorAlgebra : check(tensors.isNotEmpty()) { "List must have at least 1 element" } val n = tensors.size val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } + check(tensors.all { it.shape contentEquals Shape(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( - intArrayOf(n, n), + Shape(n, n), DoubleBuffer(n * n) { 0.0 } ) for (i in 0 until n) { @@ -772,7 +783,7 @@ public open class DoubleTensorAlgebra : ): Triple { checkSquareMatrix(luTensor.shape) check( - luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || + luTensor.shape.first(luTensor.shape.size - 2) contentEquals pivotsTensor.shape.first(pivotsTensor.shape.size - 1) || luTensor.shape.last() == pivotsTensor.shape.last() - 1 ) { "Inappropriate shapes of input tensors" } @@ -843,9 +854,10 @@ public open class DoubleTensorAlgebra : return qTensor to rTensor } - override fun StructureND.svd(): Triple = + override fun StructureND.svd(): Triple, StructureND, StructureND> = svd(epsilon = 1e-10) + /** * Singular Value Decomposition. * @@ -859,13 +871,13 @@ public open class DoubleTensorAlgebra : * i.e., the precision with which the cosine approaches 1 in an iterative algorithm. * @return a triple `Triple(U, S, V)`. */ - public fun StructureND.svd(epsilon: Double): Triple { + public fun StructureND.svd(epsilon: Double): Triple, StructureND, StructureND> { 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 commonShape = shape.slice(0 until size - 2) + val (n, m) = shape.slice(size - 2 until size) + val uTensor = zeros(commonShape + Shape(min(n, m), n)) + val sTensor = zeros(commonShape + Shape(min(n, m))) + val vTensor = zeros(commonShape + Shape(min(n, m), m)) val matrices = asDoubleTensor().matrices val uTensors = uTensor.matrices @@ -879,7 +891,7 @@ public open class DoubleTensorAlgebra : sTensorVectors[index], vTensors[index] ) - val matrixSize = matrix.shape.reduce { acc, i -> acc * i } + val matrixSize = matrix.shape.linearSize val curMatrix = DoubleTensor( matrix.shape, matrix.source.view(0, matrixSize) @@ -901,7 +913,7 @@ public open class DoubleTensorAlgebra : * and when the cosine approaches 1 in the SVD algorithm. * @return a pair `eigenvalues to eigenvectors`. */ - public fun StructureND.symEigSvd(epsilon: Double): Pair { + public fun StructureND.symEigSvd(epsilon: Double): Pair> { //TODO optimize conversion checkSymmetric(asDoubleTensor(), epsilon) @@ -925,7 +937,7 @@ public open class DoubleTensorAlgebra : matrix.asDoubleTensor2D().cleanSym(n) } - val eig = (utv dot s.view(shp)).view(s.shape) + val eig = (utv dot s.asDoubleTensor().view(shp)).view(s.shape) return eig to v } @@ -934,8 +946,8 @@ public open class DoubleTensorAlgebra : checkSymmetric(asDoubleTensor(), epsilon) val size = this.dimension - val eigenvectors = zeros(this.shape) - val eigenvalues = zeros(this.shape.sliceArray(0 until size - 1)) + val eigenvectors = zeros(shape) + val eigenvalues = zeros(shape.slice(0 until size - 1)) var eigenvalueStart = 0 var eigenvectorStart = 0 @@ -976,9 +988,11 @@ public open class DoubleTensorAlgebra : val n = shape.size - val detTensorShape = IntArray(n - 1) { i -> shape[i] } - detTensorShape[n - 2] = 1 - val resBuffer = DoubleBuffer(detTensorShape.reduce(Int::times)) { 0.0 } + val detTensorShape = Shape(IntArray(n - 1) { i -> shape[i] }.apply { + set(n - 2, 1) + }) + + val resBuffer = DoubleBuffer(detTensorShape.linearSize) { 0.0 } val detTensor = DoubleTensor( detTensorShape, 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 ed96b6c8f..a99773f84 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.Shape import space.kscience.kmath.structures.* /** @@ -73,7 +75,7 @@ public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) { * Default [BufferedTensor] implementation for [Int] values */ public class IntTensor( - shape: IntArray, + shape: Shape, override val source: OffsetIntBuffer, ) : BufferedTensor(shape) { @@ -81,10 +83,12 @@ public class IntTensor( 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)) + public constructor(shape: Shape, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) + @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Int = this.source[indices.offset(index)] + @OptIn(PerformancePitfall::class) 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 index 3b00744a1..86199d19b 100644 --- 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 @@ -23,6 +23,7 @@ public open class IntTensorAlgebra : TensorAlgebra { public companion object : IntTensorAlgebra() + override val elementAlgebra: IntRing get() = IntRing @@ -88,7 +89,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun StructureND.valueOrNull(): Int? { val dt = asIntTensor() - return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + return if (dt.shape contentEquals Shape(1)) dt.source[0] else null } override fun StructureND.value(): Int = valueOrNull() @@ -101,11 +102,11 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: IntArray, array: IntArray): IntTensor { + public fun fromArray(shape: Shape, 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" + check(array.size == shape.linearSize) { + "Inconsistent shape ${shape} for buffer of size ${array.size} provided" } return IntTensor(shape, array.asBuffer()) } @@ -117,16 +118,16 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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( + override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( shape, RowStrides(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)) + val lastShape = shape.last(shape.size - 1) + val newShape = if (lastShape.isNotEmpty()) lastShape else Shape(1) + return IntTensor(newShape, dt.source.view(newShape.linearSize * i)) } /** @@ -136,9 +137,9 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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 { + public fun full(value: Int, shape: Shape): IntTensor { checkNotEmptyShape(shape) - val buffer = IntBuffer(shape.reduce(Int::times)) { value } + val buffer = IntBuffer(shape.linearSize) { value } return IntTensor(shape, buffer) } @@ -160,7 +161,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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) + public fun zeros(shape: Shape): IntTensor = full(0, shape) /** * Returns a tensor filled with the scalar value `0`, with the same shape as a given array. @@ -175,7 +176,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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) + public fun ones(shape: Shape): IntTensor = full(1, shape) /** * Returns a tensor filled with the scalar value `1`, with the same shape as a given array. @@ -191,7 +192,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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 shape = Shape(n, n) val buffer = IntBuffer(n * n) { 0 } val res = IntTensor(shape, buffer) for (i in 0 until n) { @@ -249,32 +250,44 @@ public open class IntTensorAlgebra : TensorAlgebra { 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] + override fun StructureND.transposed(i: Int, j: Int): Tensor { + val actualI = if (i >= 0) i else shape.size + i + val actualJ = if(j>=0) j else shape.size + j + return asIntTensor().permute( + shape.transposed(actualI, actualJ) + ) { originIndex -> + originIndex.copyOf().apply { + val ith = get(actualI) + val jth = get(actualJ) + set(actualI, jth) + set(actualJ, ith) + } } - return resTensor +// // 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.toArray() +// resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } +// +// val resTensor = IntTensor(Shape(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 { + override fun Tensor.view(shape: Shape): IntTensor { checkView(asIntTensor(), shape) return IntTensor(shape, asIntTensor().source) } @@ -287,7 +300,7 @@ public open class IntTensorAlgebra : TensorAlgebra { } override fun diagonalEmbedding( - diagonalEntries: Tensor, + diagonalEntries: StructureND, offset: Int, dim1: Int, dim2: Int, @@ -311,11 +324,11 @@ public open class IntTensorAlgebra : TensorAlgebra { lessDim = greaterDim.also { greaterDim = lessDim } } - val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + val resShape = diagonalEntries.shape.slice(0 until lessDim) + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + - diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + diagonalEntries.shape.slice(lessDim until greaterDim - 1) + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + - diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + diagonalEntries.shape.slice(greaterDim - 1 until n - 1) val resTensor = zeros(resShape) for (i in 0 until diagonalEntries.asIntTensor().linearSize) { @@ -375,7 +388,7 @@ public open class IntTensorAlgebra : TensorAlgebra { 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 resShape = Shape(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart) // .take(it.asIntTensor().linearSize) @@ -399,11 +412,11 @@ public open class IntTensorAlgebra : TensorAlgebra { ): 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() + shape.first(dim) + intArrayOf(1) + shape.last(dimension - dim - 1) } else { - shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + shape.first(dim) + shape.last(dimension - dim - 1) } - val resNumElements = resShape.reduce(Int::times) + val resNumElements = resShape.linearSize val init = foldFunction(IntArray(1) { 0 }) val resTensor = IntTensor( resShape, 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 fee62c79c..dcb16b755 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.tensors.core.internal +import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.nd.* import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.max @@ -12,7 +14,7 @@ import kotlin.math.max internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { val totalMultiIndex = resTensor.indices.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() + val curMultiIndex = tensor.shape.toArray() val offset = totalMultiIndex.size - curMultiIndex.size @@ -30,7 +32,7 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } } -internal fun broadcastShapes(vararg shapes: IntArray): IntArray { +internal fun broadcastShapes(shapes: List): Shape { var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -55,15 +57,15 @@ internal fun broadcastShapes(vararg shapes: IntArray): IntArray { } } - return totalShape + return Shape(totalShape) } -internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { +internal fun broadcastTo(tensor: DoubleTensor, newShape: Shape): DoubleTensor { require(tensor.shape.size <= newShape.size) { "Tensor is not compatible with the new shape" } - val n = newShape.reduce { acc, i -> acc * i } + val n = newShape.linearSize val resTensor = DoubleTensor(newShape, DoubleArray(n).asBuffer()) for (i in tensor.shape.indices) { @@ -79,8 +81,8 @@ internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor } internal fun broadcastTensors(vararg tensors: DoubleTensor): List { - val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) - val n = totalShape.reduce { acc, i -> acc * i } + val totalShape = broadcastShapes(tensors.map { it.shape }) + val n = totalShape.linearSize return tensors.map { tensor -> val resTensor = DoubleTensor(totalShape, DoubleArray(n).asBuffer()) @@ -100,12 +102,12 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List acc * i } + val totalShape = broadcastShapes(tensors.map { it.shape.slice(0..it.shape.size - 3) }) + val n = totalShape.linearSize return buildList { for (tensor in tensors) { - val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() + val matrixShape = tensor.shape.slice(tensor.shape.size - 2 until tensor.shape.size) val matrixSize = matrixShape[0] * matrixShape[1] val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize).asBuffer()) @@ -114,10 +116,11 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List 0) { "Illegal empty shape provided" } @@ -21,15 +24,15 @@ internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmp "Illegal empty buffer provided" } -internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = - check(buffer.size == shape.reduce(Int::times)) { - "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" +internal fun checkBufferShapeConsistency(shape: Shape, buffer: DoubleArray) = + check(buffer.size == shape.linearSize) { + "Inconsistent shape ${shape} for buffer of size ${buffer.size} provided" } @PublishedApi internal fun checkShapesCompatible(a: StructureND, b: StructureND): Unit = check(a.shape contentEquals b.shape) { - "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " + "Incompatible shapes ${a.shape} and ${b.shape} " } internal fun checkTranspose(dim: Int, i: Int, j: Int) = @@ -37,10 +40,10 @@ internal fun checkTranspose(dim: Int, i: Int, j: Int) = "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: Tensor, shape: IntArray) = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) +internal fun checkView(a: Tensor, shape: Shape) = + check(a.shape.linearSize == shape.linearSize) -internal fun checkSquareMatrix(shape: IntArray) { +internal fun checkSquareMatrix(shape: Shape) { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" 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 index 22047e458..1c6e5edfb 100644 --- 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 @@ -6,7 +6,6 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.* -import space.kscience.kmath.nd.Strides.Companion.linearSizeOf import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.indices @@ -40,7 +39,7 @@ internal fun MutableStructure2D.jacobiHelper( source[i * shape[0] + j] = value } - fun maxOffDiagonal(matrix: BufferedTensor): Double { + fun maxOffDiagonal(matrix: DoubleTensor): Double { var maxOffDiagonalElement = 0.0 for (i in 0 until n - 1) { for (j in i + 1 until n) { @@ -50,7 +49,7 @@ internal fun MutableStructure2D.jacobiHelper( return maxOffDiagonalElement } - fun rotate(a: BufferedTensor, s: Double, tau: Double, i: Int, j: Int, k: Int, l: Int) { + fun rotate(a: DoubleTensor, 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) @@ -58,8 +57,8 @@ internal fun MutableStructure2D.jacobiHelper( } fun jacobiIteration( - a: BufferedTensor, - v: BufferedTensor, + a: DoubleTensor, + v: DoubleTensor, d: DoubleBuffer, z: DoubleBuffer, ) { @@ -157,7 +156,7 @@ internal val DoubleTensor.vectors: List get() { val n = shape.size val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) + val vectorShape = Shape(shape.last()) return List(linearSize / vectorOffset) { index -> val offset = index * vectorOffset @@ -174,9 +173,9 @@ internal val DoubleTensor.matrices: List 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 matrixShape = Shape(shape[n - 2], shape[n - 1]) - val size = linearSizeOf(matrixShape) + val size = matrixShape.linearSize return List(linearSize / matrixOffset) { index -> val offset = index * matrixOffset 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 index f938d1c61..2513dedb7 100644 --- 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 @@ -5,6 +5,9 @@ package space.kscience.kmath.tensors.core.internal +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.first +import space.kscience.kmath.nd.last import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.IntBuffer import space.kscience.kmath.structures.VirtualBuffer @@ -35,7 +38,7 @@ internal fun List.concat(): IntBuffer { internal fun IntTensor.vectors(): VirtualBuffer { val n = shape.size val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) + val vectorShape = shape.last(1) return VirtualBuffer(linearSize / vectorOffset) { index -> val offset = index * vectorOffset @@ -52,7 +55,7 @@ internal val IntTensor.matrices: VirtualBuffer 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 matrixShape = Shape(shape[n - 2], shape[n - 1]) return VirtualBuffer(linearSize / matrixOffset) { index -> val offset = index * matrixOffset 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 cc699e1bb..b01e67eee 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 @@ -5,10 +5,7 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.IntBuffer @@ -98,7 +95,7 @@ internal fun StructureND.setUpPivots(): IntTensor { pivotsShape[n - 2] = m + 1 return IntTensor( - pivotsShape, + Shape(pivotsShape), IntBuffer(pivotsShape.reduce(Int::times)) { 0 } ) } @@ -243,10 +240,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) val b: DoubleTensor if (n > m) { b = a.transposed(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), DoubleBuffer.randomUnitVector(m, 0)) + v = DoubleTensor(Shape(m), DoubleBuffer.randomUnitVector(m, 0)) } else { b = a.dot(a.transposed(0, 1)) - v = DoubleTensor(intArrayOf(n), DoubleBuffer.randomUnitVector(n, 0)) + v = DoubleTensor(Shape(n), DoubleBuffer.randomUnitVector(n, 0)) } var lastV: DoubleTensor @@ -278,7 +275,7 @@ internal fun DoubleTensorAlgebra.svdHelper( 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.asBuffer())) + a = a - singularValue.times(DoubleTensor(Shape(u.shape[0], v.shape[0]), outerProduct.asBuffer())) } var v: DoubleTensor var u: DoubleTensor 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 c5ba98811..91fcc90ee 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 @@ -6,6 +6,8 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.asList +import space.kscience.kmath.nd.last import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler @@ -92,7 +94,7 @@ public fun DoubleTensor.toPrettyString(): String = buildString { append(']') charOffset -= 1 - index.reversed().zip(shape.reversed()).drop(1).forEach { (ind, maxInd) -> + index.reversed().zip(shape.asList().reversed()).drop(1).forEach { (ind, maxInd) -> if (ind != maxInd - 1) { return@forEach } 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 619d5c753..7e30c7965 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 @@ -12,11 +12,11 @@ import space.kscience.kmath.nd.Shape import kotlin.jvm.JvmName @JvmName("varArgOne") -public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(intArrayOf(*shape)) +public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(Shape(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(vararg shape: Int): DoubleTensor = zeros(Shape(shape)) public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) 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 index 61bf2341e..3b0d15400 100644 --- 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 @@ -5,9 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.DoubleBufferND -import space.kscience.kmath.nd.RowStrides -import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.* import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.api.Tensor @@ -23,7 +21,7 @@ public fun StructureND.copyToTensor(): DoubleTensor = if (this is Double } else { DoubleTensor( shape, - RowStrides(this.shape).map(this::get).toDoubleArray().asBuffer(), + RowStrides(this.shape).map(this::getDouble).toDoubleArray().asBuffer(), ) } @@ -36,7 +34,7 @@ public fun StructureND.toDoubleTensor(): DoubleTensor { } else { val tensor = DoubleTensorAlgebra.zeroesLike(this) indices.forEach { - tensor[it] = get(it).toDouble() + tensor[it] = getInt(it).toDouble() } return tensor } @@ -59,7 +57,7 @@ public fun StructureND.asDoubleTensor(): DoubleTensor = if (this is Doub public fun StructureND.asIntTensor(): IntTensor = when (this) { is IntTensor -> this else -> IntTensor( - this.shape, - RowStrides(this.shape).map(this::get).toIntArray().asBuffer() + shape, + RowStrides(shape).map(this::getInt).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 6a99b9ba8..5940d44e9 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors import space.kscience.kmath.tensors.core.internal.broadcastShapes @@ -19,38 +21,38 @@ internal class TestBroadcasting { fun testBroadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( - intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) - ) contentEquals intArrayOf(1, 2, 3) + listOf(Shape(2, 3), Shape(1, 3), Shape(1, 1, 1)) + ) contentEquals Shape(1, 2, 3) ) assertTrue( broadcastShapes( - intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7), intArrayOf(5, 1, 7) - ) contentEquals intArrayOf(5, 6, 7) + listOf(Shape(6, 7), Shape(5, 6, 1), Shape(7), Shape(5, 1, 7)) + ) contentEquals Shape(5, 6, 7) ) } @Test fun testBroadcastTo() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val res = broadcastTo(tensor2, tensor1.shape) - assertTrue(res.shape contentEquals intArrayOf(2, 3)) + assertTrue(res.shape contentEquals Shape(2, 3)) assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) } @Test fun testBroadcastTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) + assertTrue(res[1].shape contentEquals Shape(1, 2, 3)) + assertTrue(res[2].shape contentEquals Shape(1, 2, 3)) 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)) @@ -59,15 +61,15 @@ internal class TestBroadcasting { @Test fun testBroadcastOuterTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3)) - assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1)) + assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) + assertTrue(res[1].shape contentEquals Shape(1, 1, 3)) + assertTrue(res[2].shape contentEquals Shape(1, 1, 1)) 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)) @@ -76,37 +78,37 @@ internal class TestBroadcasting { @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 tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(Shape(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) + val tensor2 = fromArray(Shape(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) + val tensor3 = fromArray(Shape(1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals intArrayOf(4, 2, 5, 3, 2, 3)) - assertTrue(res[1].shape contentEquals intArrayOf(4, 2, 5, 3, 3, 3)) - assertTrue(res[2].shape contentEquals intArrayOf(4, 2, 5, 3, 1, 1)) + assertTrue(res[0].shape contentEquals Shape(4, 2, 5, 3, 2, 3)) + assertTrue(res[1].shape contentEquals Shape(4, 2, 5, 3, 3, 3)) + assertTrue(res[2].shape contentEquals Shape(4, 2, 5, 3, 1, 1)) } @Test fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) val tensor21 = tensor2 - tensor1 val tensor31 = tensor3 - tensor1 val tensor32 = tensor3 - tensor2 - assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) + assertTrue(tensor21.shape contentEquals Shape(2, 3)) 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.shape contentEquals Shape(1, 2, 3)) assertTrue( 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.shape contentEquals Shape(1, 1, 3)) 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 4bc2e3bdb..f098eecb0 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 @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Shape import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.asBuffer import kotlin.math.* @@ -13,7 +14,7 @@ import kotlin.test.assertTrue internal class TestDoubleAnalyticTensorAlgebra { - val shape = intArrayOf(2, 1, 3, 2) + val shape = Shape(2, 1, 3, 2) val buffer = doubleArrayOf( 27.1, 20.0, 19.84, 23.123, 3.0, 2.0, @@ -102,7 +103,7 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor.floor() eq expectedTensor(::floor) } } - val shape2 = intArrayOf(2, 2) + val shape2 = Shape(2, 2) val buffer2 = doubleArrayOf( 1.0, 2.0, -3.0, 4.0 @@ -114,13 +115,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.min() == -3.0 } assertTrue { tensor2.min(0, true) eq fromArray( - intArrayOf(1, 2), + Shape(1, 2), doubleArrayOf(-3.0, 2.0) ) } assertTrue { tensor2.min(1, false) eq fromArray( - intArrayOf(2), + Shape(2), doubleArrayOf(1.0, -3.0) ) } @@ -131,13 +132,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.max() == 4.0 } assertTrue { tensor2.max(0, true) eq fromArray( - intArrayOf(1, 2), + Shape(1, 2), doubleArrayOf(1.0, 4.0) ) } assertTrue { tensor2.max(1, false) eq fromArray( - intArrayOf(2), + Shape(2), doubleArrayOf(2.0, 4.0) ) } @@ -148,13 +149,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } assertTrue { tensor2.sum(0, true) eq fromArray( - intArrayOf(1, 2), + Shape(1, 2), doubleArrayOf(-2.0, 6.0) ) } assertTrue { tensor2.sum(1, false) eq fromArray( - intArrayOf(2), + Shape(2), doubleArrayOf(3.0, 1.0) ) } @@ -165,13 +166,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } assertTrue { tensor2.mean(0, true) eq fromArray( - intArrayOf(1, 2), + Shape(1, 2), doubleArrayOf(-1.0, 3.0) ) } assertTrue { tensor2.mean(1, false) eq fromArray( - intArrayOf(2), + Shape(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 1c23cff18..b9f845bb2 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs @@ -17,7 +19,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testDetLU() = DoubleTensorAlgebra { val tensor = fromArray( - intArrayOf(2, 2, 2), + Shape(2, 2, 2), doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -27,7 +29,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - intArrayOf(2, 1), + Shape(2, 1), doubleArrayOf( -1.0, -7.0 @@ -43,7 +45,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDet() = DoubleTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( - intArrayOf(3, 3), doubleArrayOf( + Shape(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, 1.4391, 1.7772, 0.4055, -0.4845, 0.4055, 0.7519 @@ -57,7 +59,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDetSingle() = DoubleTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( - intArrayOf(1, 1), doubleArrayOf( + Shape(1, 1), doubleArrayOf( expectedValue ) ) @@ -68,7 +70,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testInvLU() = DoubleTensorAlgebra { val tensor = fromArray( - intArrayOf(2, 2, 2), + Shape(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 2.0, @@ -78,7 +80,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - intArrayOf(2, 2, 2), doubleArrayOf( + Shape(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 0.5, 0.0, 1.0, @@ -92,14 +94,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testScalarProduct() = DoubleTensorAlgebra { - val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) - val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) + val a = fromArray(Shape(3), doubleArrayOf(1.8, 2.5, 6.8)) + val b = fromArray(Shape(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test fun testQR() = DoubleTensorAlgebra { - val shape = intArrayOf(2, 2, 2) + val shape = Shape(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -120,7 +122,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testLU() = DoubleTensorAlgebra { - val shape = intArrayOf(2, 2, 2) + val shape = Shape(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -140,9 +142,9 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleTensorAlgebra { - val tensor = randomNormal(intArrayOf(2, 5, 5), 0) + val tensor = randomNormal(Shape(2, 5, 5), 0) val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( - fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) + fromArray(Shape(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() val sigmChol = low matmul low.transposed() @@ -151,24 +153,24 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testSVD1D() = DoubleTensorAlgebra { - val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) - assertTrue(res.shape contentEquals intArrayOf(2)) + assertTrue(res.shape contentEquals Shape(2)) assertTrue { abs(abs(res.source[0]) - 0.386) < 0.01 } assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 } } @Test 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))) + testSVDFor(fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + testSVDFor(fromArray(Shape(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test fun testBatchedSVD() = DoubleTensorAlgebra { - val tensor = randomNormal(intArrayOf(2, 5, 3), 0) + val tensor = randomNormal(Shape(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) @@ -176,7 +178,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleTensorAlgebra { - val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) + val tensor = randomNormal(shape = Shape(2, 3, 3), 0) val tensorSigma = tensor + tensor.transposed() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) 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 505031b67..f07614d05 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 @@ -21,14 +21,14 @@ internal class TestDoubleTensor { @Test fun testValue() = DoubleTensorAlgebra { val value = 12.5 - val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) + val tensor = fromArray(Shape(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @OptIn(PerformancePitfall::class) @Test fun testStrides() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(Shape(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() @@ -38,7 +38,7 @@ internal class TestDoubleTensor { @Test fun testGet() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(Shape(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor.getTensor(0).asDoubleTensor2D() assertEquals(matrix[0, 1], 5.8) @@ -67,7 +67,7 @@ internal class TestDoubleTensor { val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(intArrayOf(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(Shape(3)), doubleArray) // map to tensors val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. @@ -91,7 +91,7 @@ internal class TestDoubleTensor { @Test fun test2D() = with(DoubleTensorAlgebra) { - val tensor: DoubleTensor = structureND(intArrayOf(3, 3)) { (i, j) -> (i - j).toDouble() } + val tensor: DoubleTensor = structureND(Shape(3, 3)) { (i, j) -> (i - j).toDouble() } //println(tensor.toPrettyString()) val tensor2d = tensor.asDoubleTensor2D() assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1]) @@ -100,7 +100,7 @@ internal class TestDoubleTensor { @Test fun testMatrixIteration() = with(DoubleTensorAlgebra) { - val tensor = structureND(intArrayOf(3, 3, 3, 3)) { index -> index.sum().toDouble() } + val tensor = structureND(Shape(3, 3, 3, 3)) { index -> index.sum().toDouble() } tensor.forEachMatrix { index, matrix -> println(index.joinToString { it.toString() }) println(matrix) 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 67bebb9a7..3c693b089 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 @@ -6,6 +6,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke import space.kscience.kmath.testutils.assertBufferEquals @@ -18,62 +20,62 @@ internal class TestDoubleTensorAlgebra { @Test fun testDoublePlus() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) + val tensor = fromArray(Shape(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0)) } @Test fun testDoubleDiv() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) + val tensor = fromArray(Shape(2), doubleArrayOf(2.0, 4.0)) 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 tensor = fromArray(Shape(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0)) } @Test fun testTranspose1x1() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) + val tensor = fromArray(Shape(1), doubleArrayOf(0.0)) val res = tensor.transposed(0, 0) - assertTrue(res.source contentEquals doubleArrayOf(0.0)) - assertTrue(res.shape contentEquals intArrayOf(1)) + assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(0.0)) + assertTrue(res.shape contentEquals Shape(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 tensor = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transposed(1, 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)) + assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.shape contentEquals Shape(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 tensor = fromArray(Shape(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) 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.shape contentEquals Shape(2, 1, 3)) + assertTrue(res02.shape contentEquals Shape(3, 2, 1)) + assertTrue(res12.shape contentEquals Shape(1, 3, 2)) - 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)) + assertTrue(res01.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test fun testLinearStructure() = DoubleTensorAlgebra { - val shape = intArrayOf(3) + val shape = Shape(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) val tensorC = full(value = 789.3, shape = shape) @@ -105,28 +107,28 @@ internal class TestDoubleTensorAlgebra { @Test fun testDot() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(intArrayOf(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) - val tensor4 = fromArray(intArrayOf(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) - val tensor5 = fromArray(intArrayOf(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor11 = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(Shape(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) + val tensor4 = fromArray(Shape(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) + val tensor5 = fromArray(Shape(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) val res12 = tensor1.dot(tensor2) assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0)) - assertTrue(res12.shape contentEquals intArrayOf(2)) + assertTrue(res12.shape contentEquals Shape(2)) val res32 = tensor3.matmul(tensor2) assertTrue(res32.source contentEquals doubleArrayOf(-140.0)) - assertTrue(res32.shape contentEquals intArrayOf(1, 1)) + assertTrue(res32.shape contentEquals Shape(1, 1)) val res22 = tensor2.dot(tensor2) assertTrue(res22.source contentEquals doubleArrayOf(1400.0)) - assertTrue(res22.shape contentEquals intArrayOf(1)) + assertTrue(res22.shape contentEquals Shape(1)) val res11 = tensor1.dot(tensor11) assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) - assertTrue(res11.shape contentEquals intArrayOf(2, 2)) + assertTrue(res11.shape contentEquals Shape(2, 2)) val res45 = tensor4.matmul(tensor5) assertTrue( @@ -135,44 +137,44 @@ internal class TestDoubleTensorAlgebra { 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)) + assertTrue(res45.shape contentEquals Shape(2, 3, 3)) } @Test fun testDiagonalEmbedding() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) - 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)) + val tensor1 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = zeros(Shape(2, 3, 4, 5)) assertTrue( diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 5, 5) + Shape(2, 3, 4, 5, 5) ) assertTrue( diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 6, 6) + Shape(2, 3, 4, 6, 6) ) assertTrue( diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals - intArrayOf(7, 2, 3, 7, 4) + Shape(7, 2, 3, 7, 4) ) val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) - assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3)) + assertTrue(diagonal1.shape contentEquals Shape(3, 3)) 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.shape contentEquals Shape(4, 4)) 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.shape contentEquals Shape(4, 2, 4)) assertTrue( diagonal2.source contentEquals doubleArrayOf( @@ -186,9 +188,9 @@ internal class TestDoubleTensorAlgebra { @Test fun testEq() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) + val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) assertTrue(tensor1 eq tensor1) assertTrue(tensor1 eq tensor2) @@ -202,7 +204,7 @@ internal class TestDoubleTensorAlgebra { 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 } + assertTrue { Shape(5, 5) contentEquals res.shape } assertEquals(2.0, res[4, 4]) } } 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 1b7601a14..5ac1c74a3 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 @@ -9,6 +9,7 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnsafeKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField @@ -31,8 +32,9 @@ public open class ViktorFieldOpsND : override val elementAlgebra: DoubleField get() = DoubleField - override fun structureND(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = - F64Array(*shape).apply { + @OptIn(UnsafeKMathAPI::class) + override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = + F64Array(*shape.asArray()).apply { ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.initializer(index), indices = index) } @@ -40,23 +42,26 @@ public open class ViktorFieldOpsND : override fun StructureND.unaryMinus(): StructureND = -1 * this + @OptIn(UnsafeKMathAPI::class) @PerformancePitfall override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = - F64Array(*shape).apply { - ColumnStrides(shape).asSequence().forEach { index -> + F64Array(*shape.asArray()).apply { + ColumnStrides(Shape(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(this@map[index]), indices = index) } }.asStructure() + @OptIn(UnsafeKMathAPI::class) @PerformancePitfall override fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, - ): ViktorStructureND = F64Array(*shape).apply { - ColumnStrides(shape).asSequence().forEach { index -> + ): ViktorStructureND = F64Array(*shape.asArray()).apply { + ColumnStrides(Shape(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) } }.asStructure() + @OptIn(UnsafeKMathAPI::class) @PerformancePitfall override fun zip( left: StructureND, @@ -64,7 +69,7 @@ public open class ViktorFieldOpsND : transform: DoubleField.(Double, Double) -> Double, ): ViktorStructureND { require(left.shape.contentEquals(right.shape)) - return F64Array(*left.shape).apply { + return F64Array(*left.shape.asArray()).apply { ColumnStrides(left.shape).asSequence().forEach { index -> set(value = DoubleField.transform(left[index], right[index]), indices = index) } @@ -119,13 +124,17 @@ public val DoubleField.viktorAlgebra: ViktorFieldOpsND get() = ViktorFieldOpsND @OptIn(UnstableKMathAPI::class) public open class ViktorFieldND( - override val shape: Shape, + private val shapeAsArray: IntArray, ) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { - override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } - override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } + + override val shape: Shape = Shape(shapeAsArray) + + + override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shapeAsArray).asStructure() } + override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shapeAsArray).asStructure() } override fun number(value: Number): ViktorStructureND = - F64Array.full(init = value.toDouble(), shape = shape).asStructure() + F64Array.full(init = value.toDouble(), shape = shapeAsArray).asStructure() } public fun DoubleField.viktorAlgebra(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) 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 ea279a912..cee52b06d 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 @@ -9,13 +9,16 @@ import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.MutableStructureND +import space.kscience.kmath.nd.Shape @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { - override val shape: IntArray get() = f64Buffer.shape + override val shape: Shape get() = Shape(f64Buffer.shape) + @OptIn(PerformancePitfall::class) override inline fun get(index: IntArray): Double = f64Buffer.get(*index) + @OptIn(PerformancePitfall::class) override inline fun set(index: IntArray, value: Double) { f64Buffer.set(*index, value = value) } From ee569b85f801972fd7cbd44d43abcd1df0a1b30d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 Oct 2022 13:05:39 +0300 Subject: [PATCH 13/72] Safe shapes --- .../kmath/benchmarks/NDFieldBenchmark.kt | 2 +- .../kmath/benchmarks/ViktorBenchmark.kt | 4 +- .../kmath/benchmarks/ViktorLogBenchmark.kt | 4 +- .../kmath/operations/mixedNDOperations.kt | 4 +- .../kscience/kmath/structures/NDField.kt | 2 +- .../kmath/structures/StreamDoubleFieldND.kt | 6 +- .../structures/StructureReadBenchmark.kt | 4 +- .../structures/StructureWriteBenchmark.kt | 4 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 8 +- .../space/kscience/kmath/tensors/PCA.kt | 10 +- .../kmath/tensors/dataSetNormalization.kt | 6 +- .../tensors/linearSystemSolvingWithLUP.kt | 8 +- .../kscience/kmath/tensors/neuralNetwork.kt | 12 +-- .../kscience/kmath/complex/ComplexFieldND.kt | 6 +- .../kmath/linear/BufferedLinearSpace.kt | 2 +- .../kmath/linear/DoubleLinearSpace.kt | 2 +- .../kscience/kmath/linear/VirtualMatrix.kt | 5 +- .../space/kscience/kmath/nd/AlgebraND.kt | 2 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 16 +-- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/DoubleFieldND.kt | 10 +- .../space/kscience/kmath/nd/IntRingND.kt | 6 +- .../kscience/kmath/nd/PermutedStructureND.kt | 6 +- .../kotlin/space/kscience/kmath/nd/Shape.kt | 102 ------------------ .../space/kscience/kmath/nd/ShapeIndices.kt | 10 +- .../kotlin/space/kscience/kmath/nd/ShapeND.kt | 102 ++++++++++++++++++ .../space/kscience/kmath/nd/ShortRingND.kt | 4 +- .../space/kscience/kmath/nd/Structure1D.kt | 8 +- .../space/kscience/kmath/nd/Structure2D.kt | 6 +- .../space/kscience/kmath/nd/StructureND.kt | 10 +- .../kscience/kmath/nd/VirtualStructureND.kt | 6 +- .../kscience/kmath/nd/algebraNDExtentions.kt | 6 +- .../kmath/structures/BufferAccessor2D.kt | 2 +- .../space/kscience/kmath/nd/StridesTest.kt | 4 +- .../kmath/structures/LazyStructureND.kt | 8 +- .../kscience/kmath/dimensions/Wrappers.kt | 4 +- .../kscience/kmath/histogram/HistogramND.kt | 4 +- .../histogram/UniformHistogramGroupND.kt | 2 +- .../kscience/kmath/multik/MultikTensor.kt | 4 +- .../kmath/multik/MultikTensorAlgebra.kt | 8 +- .../kscience/kmath/multik/MultikNDTest.kt | 6 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 15 +-- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 8 +- .../tensorflow/DoubleTensorFlowAlgebra.kt | 6 +- .../kmath/tensorflow/TensorFlowAlgebra.kt | 12 ++- .../kmath/tensorflow/DoubleTensorFlowOps.kt | 6 +- .../kmath/tensors/api/TensorAlgebra.kt | 4 +- .../kmath/tensors/core/BufferedTensor.kt | 4 +- .../kmath/tensors/core/DoubleTensor.kt | 8 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 40 +++---- .../kscience/kmath/tensors/core/IntTensor.kt | 6 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 20 ++-- .../tensors/core/internal/broadcastUtils.kt | 8 +- .../kmath/tensors/core/internal/checks.kt | 10 +- .../core/internal/doubleTensorHelpers.kt | 4 +- .../tensors/core/internal/intTensorHelpers.kt | 4 +- .../kmath/tensors/core/internal/linUtils.kt | 8 +- .../tensors/core/tensorAlgebraExtensions.kt | 10 +- .../kmath/tensors/core/TestBroadcasting.kt | 64 +++++------ .../core/TestDoubleAnalyticTensorAlgebra.kt | 22 ++-- .../core/TestDoubleLinearOpsAlgebra.kt | 38 +++---- .../kmath/tensors/core/TestDoubleTensor.kt | 12 +-- .../tensors/core/TestDoubleTensorAlgebra.kt | 74 ++++++------- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 8 +- .../kmath/viktor/ViktorStructureND.kt | 4 +- 66 files changed, 416 insertions(+), 408 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt 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 75c1a3ee3..3d39e89a5 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -85,7 +85,7 @@ internal class NDFieldBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) private val specializedField = DoubleField.ndAlgebra private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j 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 25ce8410a..90f3cb765 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one @@ -49,7 +49,7 @@ internal class ViktorBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) // automatically build context most suited for given type. private val doubleField = DoubleField.ndAlgebra 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 ea417e564..4ec4605ed 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -49,7 +49,7 @@ internal class ViktorLogBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val shape = Shape(dim, dim) + private val shape = ShapeND(dim, dim) // automatically build context most suited for given type. private val doubleField = DoubleField.ndAlgebra 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 8fc6e1b06..4a5d783e1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt @@ -8,14 +8,14 @@ package space.kscience.kmath.operations import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.linear.matrix import space.kscience.kmath.nd.DoubleBufferND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.viktor.ViktorStructureND import space.kscience.kmath.viktor.viktorAlgebra fun main() { - val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(Shape(2, 2)) { (i, j) -> + val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(ShapeND(2, 2)) { (i, j) -> if (i == j) 2.0 else 0.0 } 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 48d14cb4c..ba8f047a8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -29,7 +29,7 @@ fun main() { Nd4j.zeros(0) val dim = 1000 val n = 1000 - val shape = Shape(dim, dim) + val shape = ShapeND(dim, dim) // specialized nd-field for Double. It works as generic Double field as well. 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 dd1516fcd..67c9b421f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -17,7 +17,7 @@ import java.util.stream.IntStream * A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel * execution. */ -class StreamDoubleFieldND(override val shape: Shape) : FieldND, +class StreamDoubleFieldND(override val shape: ShapeND) : FieldND, NumbersAddOps>, ExtendedField> { @@ -43,7 +43,7 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): BufferND { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> val index = strides.index(offset) DoubleField.initializer(index) @@ -111,4 +111,4 @@ class StreamDoubleFieldND(override val shape: Shape) : FieldND): BufferND = arg.map { atanh(it) } } -fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(Shape(shape)) +fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape)) 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 ec05f38d0..e3e7daaae 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import kotlin.system.measureTimeMillis @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") @@ -17,7 +17,7 @@ fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } val buffer = DoubleBuffer(array) - val strides = ColumnStrides(Shape(n, n)) + val strides = ColumnStrides(ShapeND(n, n)) val structure = BufferND(strides, buffer) measureTimeMillis { 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 081bfa5c0..522eeb768 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.nd.BufferND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.map import kotlin.system.measureTimeMillis @@ -16,7 +16,7 @@ private inline fun BufferND.map(block: (T) -> R): BufferN @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 - val structure = StructureND.buffered(Shape(n, n), Buffer.Companion::auto) { 1.0 } + val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 1.0 } structure.map { it + 1 } // warm-up val time1 = measureTimeMillis { val res = structure.map { it + 1 } } println("Structure mapping finished in $time1 millis") 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 32d4176c1..40b927215 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor @@ -25,10 +25,10 @@ fun main() { DoubleTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( - Shape(5), + ShapeND(5), randSeed ) + fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) ) @@ -36,7 +36,7 @@ fun main() { // also take sample of size 20 from normal distribution for x val x = randomNormal( - Shape(20, 5), + ShapeND(20, 5), randSeed ) 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 2022b6472..78199aa8b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -17,7 +17,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // assume x is range from 0 until 10 val x = fromArray( - Shape(10), + ShapeND(10), DoubleArray(10) { it.toDouble() } ) @@ -42,13 +42,13 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // save means ans standard deviations for further recovery val mean = fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(xMean, yMean) ) println("Means:\n$mean") val std = fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(xStd, yStd) ) println("Standard deviations:\n$std") @@ -69,7 +69,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.getTensor(n) dot v.view(Shape(1, 2))) * std + mean + val restored = (datasetReduced.getTensor(n) dot v.view(ShapeND(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 248266edb..091889e8e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -14,10 +14,10 @@ import space.kscience.kmath.tensors.core.withBroadcast fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods // take dataset of 5-element vectors from normal distribution - val dataset = randomNormal(Shape(100, 5)) * 1.5 // all elements from N(0, 1.5) + val dataset = randomNormal(ShapeND(100, 5)) * 1.5 // all elements from N(0, 1.5) dataset += fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means ) 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 3eab64429..60716d0ba 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -16,13 +16,13 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // set true value of x val trueX = fromArray( - Shape(4), + ShapeND(4), doubleArrayOf(-2.0, 1.5, 6.8, -2.4) ) // and A matrix val a = fromArray( - Shape(4, 4), + ShapeND(4, 4), doubleArrayOf( 0.5, 10.5, 4.5, 1.0, 8.5, 0.9, 12.8, 0.1, @@ -65,7 +65,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // this function returns solution x of a system lx = b, l should be lower triangular fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { val n = l.shape[0] - val x = zeros(Shape(n)) + val x = zeros(ShapeND(n)) for (i in 0 until n) { x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)] } 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 1e4e339dc..52b3b556c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.invoke @@ -70,12 +70,12 @@ class Dense( private val weights: DoubleTensor = DoubleTensorAlgebra { randomNormal( - Shape(inputUnits, outputUnits), + ShapeND(inputUnits, outputUnits), seed ) * sqrt(2.0 / (inputUnits + outputUnits)) } - private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(Shape(outputUnits)) } + private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(ShapeND(outputUnits)) } override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { (input dot weights) + bias @@ -184,17 +184,17 @@ fun main() = BroadcastDoubleTensorAlgebra { //val testSize = sampleSize - trainSize // take sample of features from normal distribution - val x = randomNormal(Shape(sampleSize, features), seed) * 2.5 + val x = randomNormal(ShapeND(sampleSize, features), seed) * 2.5 x += fromArray( - Shape(5), + ShapeND(5), doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means ) // define class like '1' if the sum of features > 0 and '0' otherwise val y = fromArray( - Shape(sampleSize, 1), + ShapeND(sampleSize, 1), DoubleArray(sampleSize) { i -> if (x.getTensor(i).sum() > 0.0) { 1.0 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 cbc69ca6e..06f6cad85 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 @@ -59,7 +59,7 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND, NumbersAddOps> { @@ -71,12 +71,12 @@ public class ComplexFieldND(override val shape: Shape) : public val ComplexField.ndAlgebra: ComplexFieldOpsND get() = ComplexFieldOpsND -public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(Shape(shape)) +public fun ComplexField.ndAlgebra(vararg shape: Int): ComplexFieldND = ComplexFieldND(ShapeND(shape)) /** * Produce a context for n-dimensional operations inside this real field */ public inline fun ComplexField.withNdAlgebra(vararg shape: Int, action: ComplexFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ComplexFieldND(Shape(shape)).action() + return ComplexFieldND(ShapeND(shape)).action() } 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 52f04d76a..5976b67b1 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 @@ -21,7 +21,7 @@ public class BufferedLinearSpace>( private val ndAlgebra = BufferedRingOpsND(bufferAlgebra) override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = - ndAlgebra.structureND(Shape(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() + ndAlgebra.structureND(ShapeND(rows, columns)) { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() override fun buildVector(size: Int, initializer: A.(Int) -> T): Point = bufferAlgebra.buffer(size) { elementAlgebra.initializer(it) } 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 47ab5bece..4e7ab55ef 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 @@ -21,7 +21,7 @@ public object DoubleLinearSpace : LinearSpace { rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double - ): Matrix = DoubleFieldOpsND.structureND(Shape(rows, columns)) { (i, j) -> + ): Matrix = DoubleFieldOpsND.structureND(ShapeND(rows, columns)) { (i, j) -> DoubleField.initializer(i, j) }.as2D() 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 b7ed6e867..55b970f4a 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 @@ -5,7 +5,8 @@ package space.kscience.kmath.linear -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND + /** * The matrix where each element is evaluated each time when is being accessed. @@ -18,7 +19,7 @@ public class VirtualMatrix( public val generator: (i: Int, j: Int) -> T, ) : Matrix { - override val shape: Shape get() = Shape(rowNum, colNum) + override val shape: ShapeND get() = ShapeND(rowNum, colNum) override operator fun get(i: Int, j: Int): T = generator(i, j) } 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 101f90160..d53f5488a 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 @@ -25,7 +25,7 @@ public interface AlgebraND>: Algebra> { /** * Produces a new [StructureND] using given initializer function. */ - public fun structureND(shape: Shape, initializer: C.(IntArray) -> T): StructureND + public fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): StructureND /** * Maps elements from one structure to another one by applying [transform] to them. 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 597fc7d97..781d2e367 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 @@ -12,11 +12,11 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* public interface BufferAlgebraND> : AlgebraND { - public val indexerBuilder: (Shape) -> ShapeIndexer + public val indexerBuilder: (ShapeND) -> ShapeIndexer public val bufferAlgebra: BufferAlgebra override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): BufferND { + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): BufferND { val indexer = indexerBuilder(shape) return BufferND( indexer, @@ -47,7 +47,7 @@ public interface BufferAlgebraND> : AlgebraND { zipInline(left.toBufferND(), right.toBufferND(), transform) public companion object { - public val defaultIndexerBuilder: (Shape) -> ShapeIndexer = ::Strides + public val defaultIndexerBuilder: (ShapeND) -> ShapeIndexer = ::Strides } } @@ -99,24 +99,24 @@ internal inline fun > BufferAlgebraND.zipInline( @OptIn(PerformancePitfall::class) public open class BufferedGroupNDOps>( override val bufferAlgebra: BufferAlgebra, - override val indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + override val indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : GroupOpsND, BufferAlgebraND { override fun StructureND.unaryMinus(): StructureND = map { -it } } public open class BufferedRingOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedGroupNDOps(bufferAlgebra, indexerBuilder), RingOpsND public open class BufferedFieldOpsND>( bufferAlgebra: BufferAlgebra, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : BufferedRingOpsND(bufferAlgebra, indexerBuilder), FieldOpsND { public constructor( elementAlgebra: A, - indexerBuilder: (Shape) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, + indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, ) : this(BufferFieldOps(elementAlgebra), indexerBuilder) @OptIn(PerformancePitfall::class) @@ -131,7 +131,7 @@ public val > BufferAlgebra.nd: BufferedFieldOpsND ge public fun > BufferAlgebraND.structureND( vararg shape: Int, initializer: A.(IntArray) -> T, -): BufferND = structureND(Shape(shape), initializer) +): BufferND = structureND(ShapeND(shape), initializer) public fun , A> A.structureND( initializer: EA.(IntArray) -> T, 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 644b62ebe..55e8bbcf8 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 @@ -24,7 +24,7 @@ public open class BufferND( @PerformancePitfall override operator fun get(index: IntArray): T = buffer[indices.offset(index)] - override val shape: Shape get() = indices.shape + override val shape: ShapeND get() = indices.shape override fun toString(): String = StructureND.toString(this) } 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 182ce38d6..b5ed64108 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 @@ -74,7 +74,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D transform: DoubleField.(Double, Double) -> Double, ): BufferND = zipInline(left.toBufferND(), right.toBufferND()) { l, r -> DoubleField.transform(l, r) } - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleBufferND { val indexer = indexerBuilder(shape) return DoubleBufferND( indexer, @@ -189,7 +189,7 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D } @OptIn(UnstableKMathAPI::class) -public class DoubleFieldND(override val shape: Shape) : +public class DoubleFieldND(override val shape: ShapeND) : DoubleFieldOpsND(), FieldND, NumbersAddOps>, ExtendedField> { @@ -231,8 +231,8 @@ public class DoubleFieldND(override val shape: Shape) : public val DoubleField.ndAlgebra: DoubleFieldOpsND get() = DoubleFieldOpsND -public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(Shape(shape)) -public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(shape) +public fun DoubleField.ndAlgebra(vararg shape: Int): DoubleFieldND = DoubleFieldND(ShapeND(shape)) +public fun DoubleField.ndAlgebra(shape: ShapeND): DoubleFieldND = DoubleFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field @@ -240,5 +240,5 @@ public fun DoubleField.ndAlgebra(shape: Shape): DoubleFieldND = DoubleFieldND(sh @UnstableKMathAPI public inline fun DoubleField.withNdAlgebra(vararg shape: Int, action: DoubleFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return DoubleFieldND(Shape(shape)).run(action) + return DoubleFieldND(ShapeND(shape)).run(action) } 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 index 697e351d2..f46defeee 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt @@ -20,7 +20,7 @@ public class IntBufferND( public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.bufferAlgebra) { - override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntBufferND { + override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntBufferND { val indexer = indexerBuilder(shape) return IntBufferND( indexer, @@ -35,7 +35,7 @@ public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.buffe @OptIn(UnstableKMathAPI::class) public class IntRingND( - override val shape: Shape + override val shape: ShapeND ) : IntRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { @@ -46,5 +46,5 @@ public class IntRingND( public inline fun IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return IntRingND(Shape(shape)).run(action) + return IntRingND(ShapeND(shape)).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt index 0efc7beb0..e4ba72cec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/PermutedStructureND.kt @@ -13,7 +13,7 @@ public class PermutedStructureND( public val permutation: (IntArray) -> IntArray, ) : StructureND { - override val shape: Shape + override val shape: ShapeND get() = origin.shape @OptIn(PerformancePitfall::class) @@ -28,7 +28,7 @@ public fun StructureND.permute( public class PermutedMutableStructureND( public val origin: MutableStructureND, - override val shape: Shape = origin.shape, + override val shape: ShapeND = origin.shape, public val permutation: (IntArray) -> IntArray, ) : MutableStructureND { @@ -45,6 +45,6 @@ public class PermutedMutableStructureND( } public fun MutableStructureND.permute( - newShape: Shape = shape, + newShape: ShapeND = shape, permutation: (IntArray) -> IntArray, ): PermutedMutableStructureND = PermutedMutableStructureND(this, newShape, permutation) \ No newline at end of file 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 deleted file mode 100644 index 8dd17ab32..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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.UnsafeKMathAPI -import kotlin.jvm.JvmInline - -/** - * A read-only ND shape - */ -@JvmInline -public value class Shape(@PublishedApi internal val array: IntArray) { - public val size: Int get() = array.size - public operator fun get(index: Int): Int = array[index] - override fun toString(): String = array.contentToString() -} - -public inline fun Shape.forEach(block: (value: Int) -> Unit): Unit = array.forEach(block) - -public inline fun Shape.forEachIndexed(block: (index: Int, value: Int) -> Unit): Unit = array.forEachIndexed(block) - -public infix fun Shape.contentEquals(other: Shape): Boolean = array.contentEquals(other.array) - -public fun Shape.contentHashCode(): Int = array.contentHashCode() - -public val Shape.indices: IntRange get() = array.indices -public val Shape.linearSize: Int get() = array.reduce(Int::times) - -public fun Shape.slice(range: IntRange): Shape = Shape(array.sliceArray(range)) - -public fun Shape.last(): Int = array.last() - -/** - * A shape including last [n] dimensions of this shape - */ -public fun Shape.last(n: Int): Shape = Shape(array.copyOfRange(size - n, size)) - -public fun Shape.first(): Int = array.first() - -/** - * A shape including first [n] dimensions of this shape - */ -public fun Shape.first(n: Int): Shape = Shape(array.copyOfRange(0, n)) - -public operator fun Shape.plus(add: IntArray): Shape = Shape(array + add) - -public operator fun Shape.plus(add: Shape): Shape = Shape(array + add.array) - -public fun Shape.isEmpty(): Boolean = size == 0 -public fun Shape.isNotEmpty(): Boolean = size > 0 - -public fun Shape.transposed(i: Int, j: Int): Shape = Shape(array.copyOf().apply { - val ith = get(i) - val jth = get(j) - set(i, jth) - set(j, ith) -}) - -public operator fun Shape.component1(): Int = get(0) -public operator fun Shape.component2(): Int = get(1) -public operator fun Shape.component3(): Int = get(2) - -/** - * Convert to array with protective copy - */ -public fun Shape.toArray(): IntArray = array.copyOf() - -@UnsafeKMathAPI -public fun Shape.asArray(): IntArray = array - -public fun Shape.asList(): List = array.asList() - - -/** - * 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: Shape, public val actual: Shape) : - RuntimeException("Shape $actual doesn't fit in expected shape ${expected}.") - -public class IndexOutOfShapeException(public val shape: Shape, public val index: IntArray) : - RuntimeException("Index ${index.contentToString()} is out of shape ${shape}") - -public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = Shape(intArrayOf(shapeFirst, *shapeRest)) - -public interface WithShape { - public val shape: Shape - - public val indices: ShapeIndexer get() = ColumnStrides(shape) -} - -internal fun requireIndexInShape(index: IntArray, shape: Shape) { - if (index.size != shape.size) throw IndexOutOfShapeException(shape, index) - shape.forEachIndexed { axis, axisShape -> - if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(shape, index) - } -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index d2ea302fd..37e0c7b5e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -12,7 +12,7 @@ import kotlin.native.concurrent.ThreadLocal * A converter from linear index to multivariate index */ public interface ShapeIndexer : Iterable { - public val shape: Shape + public val shape: ShapeND /** * Get linear index from multidimensional index @@ -68,7 +68,7 @@ public abstract class Strides : ShapeIndexer { /** * Column-first [Strides]. Columns are represented as continuous arrays */ -public class ColumnStrides(override val shape: Shape) : Strides() { +public class ColumnStrides(override val shape: ShapeND) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -118,7 +118,7 @@ public class ColumnStrides(override val shape: Shape) : Strides() { * * @param shape the shape of the tensor. */ -public class RowStrides(override val shape: Shape) : Strides() { +public class RowStrides(override val shape: ShapeND) : Strides() { override val strides: IntArray by lazy { val nDim = shape.size @@ -163,9 +163,9 @@ public class RowStrides(override val shape: Shape) : Strides() { } @ThreadLocal -private val defaultStridesCache = HashMap() +private val defaultStridesCache = HashMap() /** * Cached builder for default strides */ -public fun Strides(shape: Shape): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of file +public fun Strides(shape: ShapeND): Strides = defaultStridesCache.getOrPut(shape) { RowStrides(shape) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt new file mode 100644 index 000000000..63728e94f --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2018-2022 KMath 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.UnsafeKMathAPI +import kotlin.jvm.JvmInline + +/** + * A read-only ND shape + */ +@JvmInline +public value class ShapeND(@PublishedApi internal val array: IntArray) { + public val size: Int get() = array.size + public operator fun get(index: Int): Int = array[index] + override fun toString(): String = array.contentToString() +} + +public inline fun ShapeND.forEach(block: (value: Int) -> Unit): Unit = array.forEach(block) + +public inline fun ShapeND.forEachIndexed(block: (index: Int, value: Int) -> Unit): Unit = array.forEachIndexed(block) + +public infix fun ShapeND.contentEquals(other: ShapeND): Boolean = array.contentEquals(other.array) + +public fun ShapeND.contentHashCode(): Int = array.contentHashCode() + +public val ShapeND.indices: IntRange get() = array.indices +public val ShapeND.linearSize: Int get() = array.reduce(Int::times) + +public fun ShapeND.slice(range: IntRange): ShapeND = ShapeND(array.sliceArray(range)) + +public fun ShapeND.last(): Int = array.last() + +/** + * A shape including last [n] dimensions of this shape + */ +public fun ShapeND.last(n: Int): ShapeND = ShapeND(array.copyOfRange(size - n, size)) + +public fun ShapeND.first(): Int = array.first() + +/** + * A shape including first [n] dimensions of this shape + */ +public fun ShapeND.first(n: Int): ShapeND = ShapeND(array.copyOfRange(0, n)) + +public operator fun ShapeND.plus(add: IntArray): ShapeND = ShapeND(array + add) + +public operator fun ShapeND.plus(add: ShapeND): ShapeND = ShapeND(array + add.array) + +public fun ShapeND.isEmpty(): Boolean = size == 0 +public fun ShapeND.isNotEmpty(): Boolean = size > 0 + +public fun ShapeND.transposed(i: Int, j: Int): ShapeND = ShapeND(array.copyOf().apply { + val ith = get(i) + val jth = get(j) + set(i, jth) + set(j, ith) +}) + +public operator fun ShapeND.component1(): Int = get(0) +public operator fun ShapeND.component2(): Int = get(1) +public operator fun ShapeND.component3(): Int = get(2) + +/** + * Convert to array with protective copy + */ +public fun ShapeND.toArray(): IntArray = array.copyOf() + +@UnsafeKMathAPI +public fun ShapeND.asArray(): IntArray = array + +public fun ShapeND.asList(): List = array.asList() + + +/** + * 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: ShapeND, public val actual: ShapeND) : + RuntimeException("Shape $actual doesn't fit in expected shape ${expected}.") + +public class IndexOutOfShapeException(public val shape: ShapeND, public val index: IntArray) : + RuntimeException("Index ${index.contentToString()} is out of shape ${shape}") + +public fun ShapeND(shapeFirst: Int, vararg shapeRest: Int): ShapeND = ShapeND(intArrayOf(shapeFirst, *shapeRest)) + +public interface WithShape { + public val shape: ShapeND + + public val indices: ShapeIndexer get() = ColumnStrides(shape) +} + +internal fun requireIndexInShape(index: IntArray, shape: ShapeND) { + if (index.size != shape.size) throw IndexOutOfShapeException(shape, index) + shape.forEachIndexed { axis, axisShape -> + if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(shape, index) + } +} 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 d34c722a1..34d748b3f 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 @@ -18,7 +18,7 @@ public sealed class ShortRingOpsND : BufferedRingOpsND(ShortRi @OptIn(UnstableKMathAPI::class) public class ShortRingND( - override val shape: Shape + override val shape: ShapeND ) : ShortRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { @@ -30,5 +30,5 @@ public class ShortRingND( public inline fun ShortRing.withNdAlgebra(vararg shape: Int, action: ShortRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ShortRingND(Shape(shape)).run(action) + return ShortRingND(ShapeND(shape)).run(action) } 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 51a3d7fd0..ba48e25ce 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 @@ -46,7 +46,7 @@ public interface MutableStructure1D : Structure1D, MutableStructureND, */ @JvmInline private value class Structure1DWrapper(val structure: StructureND) : Structure1D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val size: Int get() = structure.shape[0] @PerformancePitfall @@ -60,7 +60,7 @@ private value class Structure1DWrapper(val structure: StructureND) : S * A 1D wrapper for a mutable nd-structure */ private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val size: Int get() = structure.shape[0] @PerformancePitfall @@ -90,7 +90,7 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) */ @JvmInline private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { - override val shape: Shape get() = Shape(buffer.size) + override val shape: ShapeND get() = ShapeND(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall @@ -102,7 +102,7 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D< } internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { - override val shape: Shape get() = Shape(buffer.size) + override val shape: ShapeND get() = ShapeND(buffer.size) override val size: Int get() = buffer.size @PerformancePitfall 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 d10c43c25..a9c6c2748 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 @@ -29,7 +29,7 @@ public interface Structure2D : StructureND { */ public val colNum: Int - override val shape: Shape get() = Shape(rowNum, colNum) + override val shape: ShapeND get() = ShapeND(rowNum, colNum) /** * The buffer of rows of this structure. It gets elements from the structure dynamically. @@ -102,7 +102,7 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { */ @JvmInline private value class Structure2DWrapper(val structure: StructureND) : Structure2D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] @@ -120,7 +120,7 @@ private value class Structure2DWrapper(val structure: StructureND) : S * A 2D wrapper for a mutable nd-structure */ private class MutableStructure2DWrapper(val structure: MutableStructureND) : MutableStructure2D { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] 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 baea5da15..c96843651 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 @@ -33,7 +33,7 @@ public interface StructureND : Featured, WithShape { * The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of * this structure. */ - override val shape: Shape + override val shape: ShapeND /** * The count of dimensions in this structure. It should be equal to size of [shape]. @@ -147,13 +147,13 @@ public interface StructureND : Featured, WithShape { ): BufferND = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) public fun buffered( - shape: Shape, + shape: ShapeND, bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = buffered(ColumnStrides(shape), bufferFactory, initializer) public inline fun auto( - shape: Shape, + shape: ShapeND, crossinline initializer: (IntArray) -> T, ): BufferND = auto(ColumnStrides(shape), initializer) @@ -162,13 +162,13 @@ public interface StructureND : Featured, WithShape { vararg shape: Int, crossinline initializer: (IntArray) -> T, ): BufferND = - auto(ColumnStrides(Shape(shape)), initializer) + auto(ColumnStrides(ShapeND(shape)), initializer) public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): BufferND = auto(type, ColumnStrides(Shape(shape)), initializer) + ): BufferND = auto(type, ColumnStrides(ShapeND(shape)), initializer) } } 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 index e5edeef7f..4932dca41 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI public open class VirtualStructureND( - override val shape: Shape, + override val shape: ShapeND, public val producer: (IntArray) -> T, ) : StructureND { @@ -22,12 +22,12 @@ public open class VirtualStructureND( @UnstableKMathAPI public class VirtualDoubleStructureND( - shape: Shape, + shape: ShapeND, producer: (IntArray) -> Double, ) : VirtualStructureND(shape, producer) @UnstableKMathAPI public class VirtualIntStructureND( - shape: Shape, + shape: ShapeND, 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 1b7bd20db..f0d4bd7f5 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 @@ -15,9 +15,9 @@ public fun > AlgebraND.structureND( shapeFirst: Int, vararg shapeRest: Int, initializer: A.(IntArray) -> T -): StructureND = structureND(Shape(shapeFirst, *shapeRest), initializer) +): StructureND = structureND(ShapeND(shapeFirst, *shapeRest), initializer) -public fun > AlgebraND.zero(shape: Shape): StructureND = structureND(shape) { zero } +public fun > AlgebraND.zero(shape: ShapeND): StructureND = structureND(shape) { zero } @JvmName("zeroVarArg") public fun > AlgebraND.zero( @@ -25,7 +25,7 @@ public fun > AlgebraND.zero( vararg shapeRest: Int, ): StructureND = structureND(shapeFirst, *shapeRest) { zero } -public fun > AlgebraND.one(shape: Shape): StructureND = structureND(shape) { one } +public fun > AlgebraND.one(shape: ShapeND): StructureND = structureND(shape) { one } @JvmName("oneVarArg") public fun > AlgebraND.one( 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 b1b6fba9f..48f3e919b 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 @@ -28,7 +28,7 @@ internal class BufferAccessor2D( //TODO optimize wrapper fun MutableBuffer.collect(): Structure2D = StructureND.buffered( - ColumnStrides(Shape(rowNum, colNum)), + ColumnStrides(ShapeND(rowNum, colNum)), factory ) { (i, j) -> get(i, j) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt index 7044eb930..e6335f652 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/StridesTest.kt @@ -10,7 +10,7 @@ import kotlin.test.Test class StridesTest { @Test fun checkRowBasedStrides() { - val strides = RowStrides(Shape(3, 3)) + val strides = RowStrides(ShapeND(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ @@ -24,7 +24,7 @@ class StridesTest { @Test fun checkColumnBasedStrides() { - val strides = ColumnStrides(Shape(3, 3)) + val strides = ColumnStrides(ShapeND(3, 3)) var counter = 0 for(i in 0..2){ for(j in 0..2){ 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 97e27df96..1f717658e 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 @@ -9,12 +9,12 @@ import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND public class LazyStructureND( public val scope: CoroutineScope, - override val shape: Shape, + override val shape: ShapeND, public val function: suspend (IntArray) -> T, ) : StructureND { private val cache: MutableMap> = HashMap() @@ -35,20 +35,24 @@ public class LazyStructureND( } } +@OptIn(PerformancePitfall::class) public fun StructureND.async(index: IntArray): Deferred = if (this is LazyStructureND) this@async.async(index) else CompletableDeferred(get(index)) +@OptIn(PerformancePitfall::class) public suspend fun StructureND.await(index: IntArray): T = if (this is LazyStructureND) await(index) else get(index) /** * PENDING would benefit from KEEP-176 */ +@OptIn(PerformancePitfall::class) public inline fun StructureND.mapAsyncIndexed( scope: CoroutineScope, crossinline function: suspend (T, index: IntArray) -> R, ): LazyStructureND = LazyStructureND(scope, shape) { index -> function(get(index), index) } +@OptIn(PerformancePitfall::class) public inline fun StructureND.mapAsync( scope: CoroutineScope, crossinline function: suspend (T) -> R, 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 30c84d848..dde2d4fcf 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.dimensions import space.kscience.kmath.linear.* -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring @@ -48,7 +48,7 @@ public interface DMatrix : Structure2D { public value class DMatrixWrapper( private val structure: Structure2D, ) : DMatrix { - override val shape: Shape get() = structure.shape + override val shape: ShapeND get() = structure.shape override val rowNum: Int get() = shape[0] override val colNum: Int get() = shape[1] override operator fun get(i: Int, j: Int): T = structure[i, j] 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 06320c8d9..623452422 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 @@ -10,7 +10,7 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.FieldOpsND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations @@ -45,7 +45,7 @@ public class HistogramND, D : Domain, V : Any>( */ public interface HistogramGroupND, D : Domain, V : Any> : Group>, ScaleOperations> { - public val shape: Shape + public val shape: ShapeND public val valueAlgebraND: FieldOpsND //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), /** 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 cf8b59087..f22ea9776 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 @@ -39,7 +39,7 @@ public class UniformHistogramGroupND>( public val dimension: Int get() = lower.size - override val shape: Shape = Shape(IntArray(binNums.size) { binNums[it] + 2 }) + override val shape: ShapeND = ShapeND(IntArray(binNums.size) { binNums[it] + 2 }) private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } 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 index 88c004c7b..ae526873d 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -7,13 +7,13 @@ 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.nd.ShapeND 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() = Shape(array.shape) + override val shape: ShapeND get() = ShapeND(array.shape) @PerformancePitfall override fun get(index: IntArray): T = array[index] diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 99cbc3193..1736b48e3 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -32,7 +32,7 @@ public abstract class MultikTensorAlgebra>( protected val multikStat: Statistics = multikEngine.getStatistics() @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): MultikTensor { val strides = ColumnStrides(shape) val memoryView = initMemoryView(strides.linearSize, type) strides.asSequence().forEachIndexed { linearIndex, tensorIndex -> @@ -123,7 +123,7 @@ public abstract class MultikTensorAlgebra>( public fun MutableMultiArray.wrap(): MultikTensor = MultikTensor(this.asDNArray()) @OptIn(PerformancePitfall::class) - override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) { + override fun StructureND.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) { get(intArrayOf(0)) } else null @@ -211,7 +211,7 @@ public abstract class MultikTensorAlgebra>( override fun StructureND.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() - override fun Tensor.view(shape: Shape): MultikTensor { + override fun Tensor.view(shape: ShapeND): MultikTensor { require(shape.asList().all { it > 0 }) require(shape.linearSize == this.shape.size) { "Cannot reshape array of size ${this.shape.size} into a new shape ${ @@ -223,7 +223,7 @@ public abstract class MultikTensorAlgebra>( } val mt = asMultik().array - return if (Shape(mt.shape).contentEquals(shape)) { + return if (ShapeND(mt.shape).contentEquals(shape)) { mt } else { @OptIn(UnsafeKMathAPI::class) diff --git a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index de54af732..afd292904 100644 --- a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.default.DefaultEngine import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -29,8 +29,8 @@ internal class MultikNDTest { fun dotResult() { val dim = 100 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225) val multikResult = with(multikAlgebra) { tensor1 dot tensor2 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 7654ec9ce..6f01233d7 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 @@ -33,7 +33,8 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.ndArray: INDArray - override fun structureND(shape: Shape, initializer: C.(IntArray) -> T): Nd4jArrayStructure { + @OptIn(PerformancePitfall::class) + override fun structureND(shape: ShapeND, initializer: C.(IntArray) -> T): Nd4jArrayStructure { @OptIn(UnsafeKMathAPI::class) val struct: Nd4jArrayStructure = Nd4j.create(*shape.asArray())!!.wrap() struct.indicesIterator().forEach { struct[it] = elementAlgebra.initializer(it) } @@ -224,10 +225,10 @@ public open class DoubleNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps +public class DoubleNd4jArrayField(override val shape: ShapeND) : DoubleNd4jArrayFieldOps(), FieldND public fun DoubleField.nd4j(shapeFirst: Int, vararg shapeRest: Int): DoubleNd4jArrayField = - DoubleNd4jArrayField(Shape(shapeFirst, * shapeRest)) + DoubleNd4jArrayField(ShapeND(shapeFirst, * shapeRest)) /** @@ -271,12 +272,12 @@ public open class FloatNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps +public class FloatNd4jArrayField(override val shape: ShapeND) : FloatNd4jArrayFieldOps(), RingND public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps public fun FloatField.nd4j(shapeFirst: Int, vararg shapeRest: Int): FloatNd4jArrayField = - FloatNd4jArrayField(Shape(shapeFirst, * shapeRest)) + FloatNd4jArrayField(ShapeND(shapeFirst, * shapeRest)) /** * Represents [RingND] over [Nd4jArrayIntStructure]. @@ -312,7 +313,7 @@ public open class IntNd4jArrayRingOps : Nd4jArrayRingOps { public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps -public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND +public class IntNd4jArrayRing(override val shape: ShapeND) : IntNd4jArrayRingOps(), RingND public fun IntRing.nd4j(shapeFirst: Int, vararg shapeRest: Int): IntNd4jArrayRing = - IntNd4jArrayRing(Shape(shapeFirst, * shapeRest)) \ No newline at end of file + IntNd4jArrayRing(ShapeND(shapeFirst, * shapeRest)) \ No newline at end of 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 60c865a02..a1405ccfb 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 @@ -21,7 +21,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { */ public abstract val ndArray: INDArray - override val shape: Shape get() = Shape(ndArray.shape().toIntArray()) + override val shape: ShapeND get() = ShapeND(ndArray.shape().toIntArray()) internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() 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 d505b3c0e..62bfe90ba 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 @@ -37,7 +37,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe */ public val StructureND.ndArray: INDArray - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): Nd4jArrayStructure + override fun structureND(shape: ShapeND, initializer: A.(IntArray) -> T): Nd4jArrayStructure @OptIn(PerformancePitfall::class) override fun StructureND.map(transform: A.(T) -> T): Nd4jArrayStructure = @@ -108,7 +108,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe ndArray.max(keepDim, dim).wrap() @OptIn(UnsafeKMathAPI::class) - override fun Tensor.view(shape: Shape): Nd4jArrayStructure = ndArray.reshape(shape.asArray()).wrap() + override fun Tensor.view(shape: ShapeND): Nd4jArrayStructure = ndArray.reshape(shape.asArray()).wrap() override fun Tensor.viewAs(other: StructureND): Nd4jArrayStructure = view(other.shape) @@ -178,7 +178,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { override fun INDArray.wrap(): Nd4jArrayStructure = asDoubleStructure() @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): Nd4jArrayStructure { val array: INDArray = Nd4j.zeros(*shape.asArray()) val indices = ColumnStrides(shape) indices.asSequence().forEach { index -> @@ -198,7 +198,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { } override fun StructureND.valueOrNull(): Double? = - if (shape contentEquals Shape(1)) ndArray.getDouble(0) else null + if (shape contentEquals ShapeND(1)) ndArray.getDouble(0) else null // TODO rewrite override fun diagonalEmbedding( 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 674485fd1..27a20aafe 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 @@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.ColumnStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.PowerOperations @@ -28,7 +28,7 @@ public class DoubleTensorFlowOutput( } -internal fun Shape.toLongArray(): LongArray = LongArray(size) { get(it).toLong() } +internal fun ShapeND.toLongArray(): LongArray = LongArray(size) { get(it).toLong() } public class DoubleTensorFlowAlgebra internal constructor( graph: Graph, @@ -37,7 +37,7 @@ public class DoubleTensorFlowAlgebra internal constructor( override val elementAlgebra: DoubleField get() = DoubleField override fun structureND( - shape: Shape, + shape: ShapeND, initializer: DoubleField.(IntArray) -> Double, ): StructureND { val res = TFloat64.tensorOf(org.tensorflow.ndarray.Shape.of(*shape.toLongArray())) { array -> 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 a1e0335f8..435b01b80 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 @@ -20,7 +20,7 @@ import org.tensorflow.types.family.TType import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnsafeKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.asArray import space.kscience.kmath.nd.contentEquals @@ -41,12 +41,14 @@ public sealed interface TensorFlowTensor : Tensor */ @JvmInline public value class TensorFlowArray(public val tensor: NdArray) : Tensor { - override val shape: Shape get() = Shape(tensor.shape().asArray().toIntArray()) + override val shape: ShapeND get() = ShapeND(tensor.shape().asArray().toIntArray()) + @PerformancePitfall override fun get(index: IntArray): T = tensor.getObject(*index.toLongArray()) //TODO implement native element sequence + @PerformancePitfall override fun set(index: IntArray, value: T) { tensor.setObject(value, *index.toLongArray()) } @@ -65,7 +67,7 @@ public abstract class TensorFlowOutput( public var output: Output = output internal set - override val shape: Shape get() = Shape(output.shape().asArray().toIntArray()) + override val shape: ShapeND get() = ShapeND(output.shape().asArray().toIntArray()) protected abstract fun org.tensorflow.Tensor.actualizeTensor(): NdArray @@ -99,7 +101,7 @@ public abstract class TensorFlowAlgebra> internal c protected abstract fun const(value: T): Constant - override fun StructureND.valueOrNull(): T? = if (shape contentEquals Shape(1)) + override fun StructureND.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) get(intArrayOf(0)) else null /** @@ -195,7 +197,7 @@ public abstract class TensorFlowAlgebra> internal c ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } - override fun Tensor.view(shape: Shape): Tensor = operate { + override fun Tensor.view(shape: ShapeND): Tensor = operate { @OptIn(UnsafeKMathAPI::class) ops.reshape(it, ops.constant(shape.asArray())) } 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 44a594299..ff11dc8fe 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField @@ -32,8 +32,8 @@ class DoubleTensorFlowOps { fun dot(){ val dim = 1000 - val tensor1 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12224) - val tensor2 = DoubleTensorAlgebra.randomNormal(shape = Shape(dim, dim), 12225) + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = ShapeND(dim, dim), 12225) DoubleField.produceWithTF { tensor1 dot tensor2 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 ec5d6f5e6..f923400c5 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.RingOpsND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Ring @@ -193,7 +193,7 @@ public interface TensorAlgebra> : RingOpsND { * @param shape the desired size * @return tensor with new shape */ - public fun Tensor.view(shape: Shape): Tensor + public fun Tensor.view(shape: ShapeND): Tensor /** * View this tensor as the same size as [other]. 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 c4266c669..a7283e4c8 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.RowStrides -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor @@ -16,7 +16,7 @@ import space.kscience.kmath.tensors.api.Tensor * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ public abstract class BufferedTensor( - override val shape: Shape, + override val shape: ShapeND, ) : Tensor { public abstract val source: MutableBuffer 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 3dfea7f8a..12e9549da 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 @@ -84,7 +84,7 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { * [DoubleTensor] always uses row-based strides */ public class DoubleTensor( - shape: Shape, + shape: ShapeND, override val source: OffsetDoubleBuffer, ) : BufferedTensor(shape), MutableStructureNDOfDouble { @@ -92,7 +92,7 @@ public class DoubleTensor( require(linearSize == source.size) { "Source buffer size must be equal tensor size" } } - public constructor(shape: Shape, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) + public constructor(shape: ShapeND, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) @OptIn(PerformancePitfall::class) @@ -147,7 +147,7 @@ public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStru override fun elements(): Sequence> = tensor.elements() @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Double = tensor[index] - override val shape: Shape get() = tensor.shape + override val shape: ShapeND get() = tensor.shape } public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D = DoubleTensor2D(this) @@ -162,7 +162,7 @@ public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: Do 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 = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) val size = matrixShape.linearSize for (i in 0 until linearSize / matrixOffset) { 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 a022f31a6..ce1778013 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 @@ -92,7 +92,7 @@ public open class DoubleTensorAlgebra : override fun StructureND.valueOrNull(): Double? { val dt = asDoubleTensor() - return if (dt.shape contentEquals Shape(1)) dt.source[0] else null + return if (dt.shape contentEquals ShapeND(1)) dt.source[0] else null } override fun StructureND.value(): Double = valueOrNull() @@ -105,7 +105,7 @@ public open class DoubleTensorAlgebra : * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: Shape, array: DoubleArray): DoubleTensor { + public fun fromArray(shape: ShapeND, array: DoubleArray): DoubleTensor { checkNotEmptyShape(shape) checkEmptyDoubleBuffer(array) checkBufferShapeConsistency(shape, array) @@ -119,7 +119,7 @@ public open class DoubleTensorAlgebra : * @param initializer mapping tensor indices to values. * @return tensor with the [shape] shape and data generated by the [initializer]. */ - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): DoubleTensor = fromArray( shape, RowStrides(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) @@ -127,7 +127,7 @@ public open class DoubleTensorAlgebra : override fun Tensor.getTensor(i: Int): DoubleTensor { val dt = asDoubleTensor() val lastShape = shape.last(shape.size - 1) - val newShape: Shape = if (lastShape.isNotEmpty()) lastShape else Shape(1) + val newShape: ShapeND = if (lastShape.isNotEmpty()) lastShape else ShapeND(1) return DoubleTensor( newShape, dt.source.view(newShape.linearSize * i, newShape.linearSize) @@ -141,7 +141,7 @@ public open class DoubleTensorAlgebra : * @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: Double, shape: Shape): DoubleTensor { + public fun full(value: Double, shape: ShapeND): DoubleTensor { checkNotEmptyShape(shape) val buffer = DoubleBuffer(shape.linearSize) { value } return DoubleTensor(shape, buffer) @@ -165,7 +165,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `0.0`, with the [shape] shape. */ - public fun zeros(shape: Shape): DoubleTensor = full(0.0, shape) + public fun zeros(shape: ShapeND): DoubleTensor = full(0.0, shape) /** * Returns a tensor filled with the scalar value `0.0`, with the same shape as a given array. @@ -180,7 +180,7 @@ public open class DoubleTensorAlgebra : * @param shape array of integers defining the shape of the output tensor. * @return tensor filled with the scalar value `1.0`, with the [shape] shape. */ - public fun ones(shape: Shape): DoubleTensor = full(1.0, shape) + public fun ones(shape: ShapeND): DoubleTensor = full(1.0, shape) /** * Returns a tensor filled with the scalar value `1.0`, with the same shape as a given array. @@ -196,7 +196,7 @@ public open class DoubleTensorAlgebra : * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. */ public fun eye(n: Int): DoubleTensor { - val shape = Shape(n, n) + val shape = ShapeND(n, n) val buffer = DoubleBuffer(n * n) { 0.0 } val res = DoubleTensor(shape, buffer) for (i in 0 until n) { @@ -306,7 +306,7 @@ public open class DoubleTensorAlgebra : // return resTensor } - override fun Tensor.view(shape: Shape): DoubleTensor { + override fun Tensor.view(shape: ShapeND): DoubleTensor { checkView(asDoubleTensor(), shape) return DoubleTensor(shape, asDoubleTensor().source) } @@ -346,7 +346,7 @@ public open class DoubleTensorAlgebra : @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { if (shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(Shape(1), DoubleBuffer(times(other).sum())) + return DoubleTensor(ShapeND(1), DoubleBuffer(times(other).sum())) } var penultimateDim = false @@ -358,7 +358,7 @@ public open class DoubleTensorAlgebra : if (shape.size == 1) { penultimateDim = true - newThis = newThis.view(Shape(1) + shape) + newThis = newThis.view(ShapeND(1) + shape) } if (other.shape.size == 1) { @@ -396,7 +396,7 @@ public open class DoubleTensorAlgebra : // } return if (penultimateDim) { - resTensor.view(resTensor.shape.first(resTensor.shape.size - 2) + Shape(resTensor.shape.last())) + resTensor.view(resTensor.shape.first(resTensor.shape.size - 2) + ShapeND(resTensor.shape.last())) } else if (lastDim) { resTensor.view(resTensor.shape.first(resTensor.shape.size - 1)) } else { @@ -506,7 +506,7 @@ public open class DoubleTensorAlgebra : * @return tensor of a given shape filled with numbers from the normal distribution * with `0.0` mean and `1.0` standard deviation. */ - public fun randomNormal(shape: Shape, seed: Long = 0): DoubleTensor = + public fun randomNormal(shape: ShapeND, seed: Long = 0): DoubleTensor = DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) /** @@ -531,7 +531,7 @@ public open class DoubleTensorAlgebra : 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 = Shape(tensors.size) + shape + val resShape = ShapeND(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart) // .take(it.asDoubleTensor().linearSize) @@ -685,9 +685,9 @@ public open class DoubleTensorAlgebra : check(tensors.isNotEmpty()) { "List must have at least 1 element" } val n = tensors.size val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals Shape(m) }) { "Tensors must have same shapes" } + check(tensors.all { it.shape contentEquals ShapeND(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( - Shape(n, n), + ShapeND(n, n), DoubleBuffer(n * n) { 0.0 } ) for (i in 0 until n) { @@ -875,9 +875,9 @@ public open class DoubleTensorAlgebra : val size = dimension val commonShape = shape.slice(0 until size - 2) val (n, m) = shape.slice(size - 2 until size) - val uTensor = zeros(commonShape + Shape(min(n, m), n)) - val sTensor = zeros(commonShape + Shape(min(n, m))) - val vTensor = zeros(commonShape + Shape(min(n, m), m)) + val uTensor = zeros(commonShape + ShapeND(min(n, m), n)) + val sTensor = zeros(commonShape + ShapeND(min(n, m))) + val vTensor = zeros(commonShape + ShapeND(min(n, m), m)) val matrices = asDoubleTensor().matrices val uTensors = uTensor.matrices @@ -988,7 +988,7 @@ public open class DoubleTensorAlgebra : val n = shape.size - val detTensorShape = Shape(IntArray(n - 1) { i -> shape[i] }.apply { + val detTensorShape = ShapeND(IntArray(n - 1) { i -> shape[i] }.apply { set(n - 2, 1) }) 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 a99773f84..a77c4de4c 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.structures.* /** @@ -75,7 +75,7 @@ public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) { * Default [BufferedTensor] implementation for [Int] values */ public class IntTensor( - shape: Shape, + shape: ShapeND, override val source: OffsetIntBuffer, ) : BufferedTensor(shape) { @@ -83,7 +83,7 @@ public class IntTensor( require(linearSize == source.size) { "Source buffer size must be equal tensor size" } } - public constructor(shape: Shape, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) + public constructor(shape: ShapeND, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) @OptIn(PerformancePitfall::class) override fun get(index: IntArray): Int = this.source[indices.offset(index)] 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 index 86199d19b..429b3ffa9 100644 --- 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 @@ -89,7 +89,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun StructureND.valueOrNull(): Int? { val dt = asIntTensor() - return if (dt.shape contentEquals Shape(1)) dt.source[0] else null + return if (dt.shape contentEquals ShapeND(1)) dt.source[0] else null } override fun StructureND.value(): Int = valueOrNull() @@ -102,7 +102,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: Shape, array: IntArray): IntTensor { + public fun fromArray(shape: ShapeND, array: IntArray): IntTensor { checkNotEmptyShape(shape) check(array.isNotEmpty()) { "Illegal empty buffer provided" } check(array.size == shape.linearSize) { @@ -118,7 +118,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param initializer mapping tensor indices to values. * @return tensor with the [shape] shape and data generated by the [initializer]. */ - override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( + override fun structureND(shape: ShapeND, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( shape, RowStrides(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() ) @@ -126,7 +126,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun Tensor.getTensor(i: Int): IntTensor { val dt = asIntTensor() val lastShape = shape.last(shape.size - 1) - val newShape = if (lastShape.isNotEmpty()) lastShape else Shape(1) + val newShape = if (lastShape.isNotEmpty()) lastShape else ShapeND(1) return IntTensor(newShape, dt.source.view(newShape.linearSize * i)) } @@ -137,7 +137,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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: Shape): IntTensor { + public fun full(value: Int, shape: ShapeND): IntTensor { checkNotEmptyShape(shape) val buffer = IntBuffer(shape.linearSize) { value } return IntTensor(shape, buffer) @@ -161,7 +161,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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: Shape): IntTensor = full(0, shape) + public fun zeros(shape: ShapeND): IntTensor = full(0, shape) /** * Returns a tensor filled with the scalar value `0`, with the same shape as a given array. @@ -176,7 +176,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @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: Shape): IntTensor = full(1, shape) + public fun ones(shape: ShapeND): IntTensor = full(1, shape) /** * Returns a tensor filled with the scalar value `1`, with the same shape as a given array. @@ -192,7 +192,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. */ public fun eye(n: Int): IntTensor { - val shape = Shape(n, n) + val shape = ShapeND(n, n) val buffer = IntBuffer(n * n) { 0 } val res = IntTensor(shape, buffer) for (i in 0 until n) { @@ -287,7 +287,7 @@ public open class IntTensorAlgebra : TensorAlgebra { // return resTensor } - override fun Tensor.view(shape: Shape): IntTensor { + override fun Tensor.view(shape: ShapeND): IntTensor { checkView(asIntTensor(), shape) return IntTensor(shape, asIntTensor().source) } @@ -388,7 +388,7 @@ public open class IntTensorAlgebra : TensorAlgebra { 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 = Shape(tensors.size) + shape + val resShape = ShapeND(tensors.size) + shape // val resBuffer: List = tensors.flatMap { // it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart) // .take(it.asIntTensor().linearSize) 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 dcb16b755..0b0325a85 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 @@ -32,7 +32,7 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } } -internal fun broadcastShapes(shapes: List): Shape { +internal fun broadcastShapes(shapes: List): ShapeND { var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -57,10 +57,10 @@ internal fun broadcastShapes(shapes: List): Shape { } } - return Shape(totalShape) + return ShapeND(totalShape) } -internal fun broadcastTo(tensor: DoubleTensor, newShape: Shape): DoubleTensor { +internal fun broadcastTo(tensor: DoubleTensor, newShape: ShapeND): DoubleTensor { require(tensor.shape.size <= newShape.size) { "Tensor is not compatible with the new shape" } @@ -120,7 +120,7 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List 0) { "Illegal empty shape provided" } @@ -24,7 +24,7 @@ internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmp "Illegal empty buffer provided" } -internal fun checkBufferShapeConsistency(shape: Shape, buffer: DoubleArray) = +internal fun checkBufferShapeConsistency(shape: ShapeND, buffer: DoubleArray) = check(buffer.size == shape.linearSize) { "Inconsistent shape ${shape} for buffer of size ${buffer.size} provided" } @@ -40,10 +40,10 @@ internal fun checkTranspose(dim: Int, i: Int, j: Int) = "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: Tensor, shape: Shape) = +internal fun checkView(a: Tensor, shape: ShapeND) = check(a.shape.linearSize == shape.linearSize) -internal fun checkSquareMatrix(shape: Shape) { +internal fun checkSquareMatrix(shape: ShapeND) { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" 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 index 1c6e5edfb..a293c8da3 100644 --- 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 @@ -156,7 +156,7 @@ internal val DoubleTensor.vectors: List get() { val n = shape.size val vectorOffset = shape[n - 1] - val vectorShape = Shape(shape.last()) + val vectorShape = ShapeND(shape.last()) return List(linearSize / vectorOffset) { index -> val offset = index * vectorOffset @@ -173,7 +173,7 @@ internal val DoubleTensor.matrices: List 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 = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) val size = matrixShape.linearSize 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 index 2513dedb7..35f0bf324 100644 --- 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.first import space.kscience.kmath.nd.last import space.kscience.kmath.operations.asSequence @@ -55,7 +55,7 @@ internal val IntTensor.matrices: VirtualBuffer 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 = Shape(shape[n - 2], shape[n - 1]) + val matrixShape = ShapeND(shape[n - 2], shape[n - 1]) return VirtualBuffer(linearSize / matrixOffset) { index -> val offset = index * matrixOffset 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 b01e67eee..44459ad14 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 @@ -95,7 +95,7 @@ internal fun StructureND.setUpPivots(): IntTensor { pivotsShape[n - 2] = m + 1 return IntTensor( - Shape(pivotsShape), + ShapeND(pivotsShape), IntBuffer(pivotsShape.reduce(Int::times)) { 0 } ) } @@ -240,10 +240,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) val b: DoubleTensor if (n > m) { b = a.transposed(0, 1).dot(a) - v = DoubleTensor(Shape(m), DoubleBuffer.randomUnitVector(m, 0)) + v = DoubleTensor(ShapeND(m), DoubleBuffer.randomUnitVector(m, 0)) } else { b = a.dot(a.transposed(0, 1)) - v = DoubleTensor(Shape(n), DoubleBuffer.randomUnitVector(n, 0)) + v = DoubleTensor(ShapeND(n), DoubleBuffer.randomUnitVector(n, 0)) } var lastV: DoubleTensor @@ -275,7 +275,7 @@ internal fun DoubleTensorAlgebra.svdHelper( outerProduct[i * v.shape[0] + j] = u.getTensor(i).value() * v.getTensor(j).value() } } - a = a - singularValue.times(DoubleTensor(Shape(u.shape[0], v.shape[0]), outerProduct.asBuffer())) + a = a - singularValue.times(DoubleTensor(ShapeND(u.shape[0], v.shape[0]), outerProduct.asBuffer())) } var v: DoubleTensor var u: DoubleTensor 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 7e30c7965..1733c1a7e 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 @@ -8,15 +8,15 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import kotlin.jvm.JvmName @JvmName("varArgOne") -public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(Shape(shape)) +public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(ShapeND(shape)) -public fun DoubleTensorAlgebra.one(shape: Shape): DoubleTensor = ones(shape) +public fun DoubleTensorAlgebra.one(shape: ShapeND): DoubleTensor = ones(shape) @JvmName("varArgZero") -public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(Shape(shape)) +public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(ShapeND(shape)) -public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) +public fun DoubleTensorAlgebra.zero(shape: ShapeND): DoubleTensor = zeros(shape) 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 5940d44e9..73aed8a7b 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors @@ -21,38 +21,38 @@ internal class TestBroadcasting { fun testBroadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( - listOf(Shape(2, 3), Shape(1, 3), Shape(1, 1, 1)) - ) contentEquals Shape(1, 2, 3) + listOf(ShapeND(2, 3), ShapeND(1, 3), ShapeND(1, 1, 1)) + ) contentEquals ShapeND(1, 2, 3) ) assertTrue( broadcastShapes( - listOf(Shape(6, 7), Shape(5, 6, 1), Shape(7), Shape(5, 1, 7)) - ) contentEquals Shape(5, 6, 7) + listOf(ShapeND(6, 7), ShapeND(5, 6, 1), ShapeND(7), ShapeND(5, 1, 7)) + ) contentEquals ShapeND(5, 6, 7) ) } @Test fun testBroadcastTo() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val res = broadcastTo(tensor2, tensor1.shape) - assertTrue(res.shape contentEquals Shape(2, 3)) + assertTrue(res.shape contentEquals ShapeND(2, 3)) assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) } @Test fun testBroadcastTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[2].shape contentEquals Shape(1, 2, 3)) + assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[2].shape contentEquals ShapeND(1, 2, 3)) 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)) @@ -61,15 +61,15 @@ internal class TestBroadcasting { @Test fun testBroadcastOuterTensors() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(1, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(1, 1, 3)) - assertTrue(res[2].shape contentEquals Shape(1, 1, 1)) + assertTrue(res[0].shape contentEquals ShapeND(1, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(1, 1, 3)) + assertTrue(res[2].shape contentEquals ShapeND(1, 1, 1)) 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)) @@ -78,37 +78,37 @@ internal class TestBroadcasting { @Test fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) - val tensor2 = fromArray(Shape(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) - val tensor3 = fromArray(Shape(1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) + val tensor2 = fromArray(ShapeND(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) + val tensor3 = fromArray(ShapeND(1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) - assertTrue(res[0].shape contentEquals Shape(4, 2, 5, 3, 2, 3)) - assertTrue(res[1].shape contentEquals Shape(4, 2, 5, 3, 3, 3)) - assertTrue(res[2].shape contentEquals Shape(4, 2, 5, 3, 1, 1)) + assertTrue(res[0].shape contentEquals ShapeND(4, 2, 5, 3, 2, 3)) + assertTrue(res[1].shape contentEquals ShapeND(4, 2, 5, 3, 3, 3)) + assertTrue(res[2].shape contentEquals ShapeND(4, 2, 5, 3, 1, 1)) } @Test fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 1), doubleArrayOf(500.0)) val tensor21 = tensor2 - tensor1 val tensor31 = tensor3 - tensor1 val tensor32 = tensor3 - tensor2 - assertTrue(tensor21.shape contentEquals Shape(2, 3)) + assertTrue(tensor21.shape contentEquals ShapeND(2, 3)) assertTrue(tensor21.source contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) - assertTrue(tensor31.shape contentEquals Shape(1, 2, 3)) + assertTrue(tensor31.shape contentEquals ShapeND(1, 2, 3)) assertTrue( tensor31.source contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) ) - assertTrue(tensor32.shape contentEquals Shape(1, 1, 3)) + assertTrue(tensor32.shape contentEquals ShapeND(1, 1, 3)) 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 f098eecb0..2ef2d87d6 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.asBuffer import kotlin.math.* @@ -14,7 +14,7 @@ import kotlin.test.assertTrue internal class TestDoubleAnalyticTensorAlgebra { - val shape = Shape(2, 1, 3, 2) + val shape = ShapeND(2, 1, 3, 2) val buffer = doubleArrayOf( 27.1, 20.0, 19.84, 23.123, 3.0, 2.0, @@ -103,7 +103,7 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor.floor() eq expectedTensor(::floor) } } - val shape2 = Shape(2, 2) + val shape2 = ShapeND(2, 2) val buffer2 = doubleArrayOf( 1.0, 2.0, -3.0, 4.0 @@ -115,13 +115,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.min() == -3.0 } assertTrue { tensor2.min(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-3.0, 2.0) ) } assertTrue { tensor2.min(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(1.0, -3.0) ) } @@ -132,13 +132,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.max() == 4.0 } assertTrue { tensor2.max(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(1.0, 4.0) ) } assertTrue { tensor2.max(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(2.0, 4.0) ) } @@ -149,13 +149,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } assertTrue { tensor2.sum(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-2.0, 6.0) ) } assertTrue { tensor2.sum(1, false) eq fromArray( - Shape(2), + ShapeND(2), doubleArrayOf(3.0, 1.0) ) } @@ -166,13 +166,13 @@ internal class TestDoubleAnalyticTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } assertTrue { tensor2.mean(0, true) eq fromArray( - Shape(1, 2), + ShapeND(1, 2), doubleArrayOf(-1.0, 3.0) ) } assertTrue { tensor2.mean(1, false) eq fromArray( - Shape(2), + ShapeND(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 b9f845bb2..d47af4a64 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.internal.svd1d @@ -19,7 +19,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testDetLU() = DoubleTensorAlgebra { val tensor = fromArray( - Shape(2, 2, 2), + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -29,7 +29,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - Shape(2, 1), + ShapeND(2, 1), doubleArrayOf( -1.0, -7.0 @@ -45,7 +45,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDet() = DoubleTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( - Shape(3, 3), doubleArrayOf( + ShapeND(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, 1.4391, 1.7772, 0.4055, -0.4845, 0.4055, 0.7519 @@ -59,7 +59,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testDetSingle() = DoubleTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( - Shape(1, 1), doubleArrayOf( + ShapeND(1, 1), doubleArrayOf( expectedValue ) ) @@ -70,7 +70,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testInvLU() = DoubleTensorAlgebra { val tensor = fromArray( - Shape(2, 2, 2), + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 2.0, @@ -80,7 +80,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val expectedTensor = fromArray( - Shape(2, 2, 2), doubleArrayOf( + ShapeND(2, 2, 2), doubleArrayOf( 1.0, 0.0, 0.0, 0.5, 0.0, 1.0, @@ -94,14 +94,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testScalarProduct() = DoubleTensorAlgebra { - val a = fromArray(Shape(3), doubleArrayOf(1.8, 2.5, 6.8)) - val b = fromArray(Shape(3), doubleArrayOf(5.5, 2.6, 6.4)) + val a = fromArray(ShapeND(3), doubleArrayOf(1.8, 2.5, 6.8)) + val b = fromArray(ShapeND(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test fun testQR() = DoubleTensorAlgebra { - val shape = Shape(2, 2, 2) + val shape = ShapeND(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -122,7 +122,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testLU() = DoubleTensorAlgebra { - val shape = Shape(2, 2, 2) + val shape = ShapeND(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, 1.0, 2.0, @@ -142,9 +142,9 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleTensorAlgebra { - val tensor = randomNormal(Shape(2, 5, 5), 0) + val tensor = randomNormal(ShapeND(2, 5, 5), 0) val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( - fromArray(Shape(2, 5), DoubleArray(10) { 0.1 }) + fromArray(ShapeND(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() val sigmChol = low matmul low.transposed() @@ -153,24 +153,24 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testSVD1D() = DoubleTensorAlgebra { - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) - assertTrue(res.shape contentEquals Shape(2)) + assertTrue(res.shape contentEquals ShapeND(2)) assertTrue { abs(abs(res.source[0]) - 0.386) < 0.01 } assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 } } @Test fun testSVD() = DoubleTensorAlgebra { - testSVDFor(fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) - testSVDFor(fromArray(Shape(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + testSVDFor(fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + testSVDFor(fromArray(ShapeND(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test fun testBatchedSVD() = DoubleTensorAlgebra { - val tensor = randomNormal(Shape(2, 5, 3), 0) + val tensor = randomNormal(ShapeND(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) @@ -178,7 +178,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleTensorAlgebra { - val tensor = randomNormal(shape = Shape(2, 3, 3), 0) + val tensor = randomNormal(shape = ShapeND(2, 3, 3), 0) val tensorSigma = tensor + tensor.transposed() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) 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 f07614d05..d01ae124b 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 @@ -21,14 +21,14 @@ internal class TestDoubleTensor { @Test fun testValue() = DoubleTensorAlgebra { val value = 12.5 - val tensor = fromArray(Shape(1), doubleArrayOf(value)) + val tensor = fromArray(ShapeND(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @OptIn(PerformancePitfall::class) @Test fun testStrides() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(ShapeND(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() @@ -38,7 +38,7 @@ internal class TestDoubleTensor { @Test fun testGet() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + val tensor = fromArray(ShapeND(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor.getTensor(0).asDoubleTensor2D() assertEquals(matrix[0, 1], 5.8) @@ -67,7 +67,7 @@ internal class TestDoubleTensor { val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(Shape(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(ColumnStrides(ShapeND(3)), doubleArray) // map to tensors val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. @@ -91,7 +91,7 @@ internal class TestDoubleTensor { @Test fun test2D() = with(DoubleTensorAlgebra) { - val tensor: DoubleTensor = structureND(Shape(3, 3)) { (i, j) -> (i - j).toDouble() } + val tensor: DoubleTensor = structureND(ShapeND(3, 3)) { (i, j) -> (i - j).toDouble() } //println(tensor.toPrettyString()) val tensor2d = tensor.asDoubleTensor2D() assertBufferEquals(DoubleBuffer(1.0, 0.0, -1.0), tensor2d.rows[1]) @@ -100,7 +100,7 @@ internal class TestDoubleTensor { @Test fun testMatrixIteration() = with(DoubleTensorAlgebra) { - val tensor = structureND(Shape(3, 3, 3, 3)) { index -> index.sum().toDouble() } + val tensor = structureND(ShapeND(3, 3, 3, 3)) { index -> index.sum().toDouble() } tensor.forEachMatrix { index, matrix -> println(index.joinToString { it.toString() }) println(matrix) 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 3c693b089..cae01bed8 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke @@ -20,53 +20,53 @@ internal class TestDoubleTensorAlgebra { @Test fun testDoublePlus() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(1.0, 2.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0)) } @Test fun testDoubleDiv() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(2.0, 4.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(2.0, 4.0)) val res = 2.0 / tensor assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5)) } @Test fun testDivDouble() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(2), doubleArrayOf(10.0, 5.0)) + val tensor = fromArray(ShapeND(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0)) } @Test fun testTranspose1x1() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1), doubleArrayOf(0.0)) + val tensor = fromArray(ShapeND(1), doubleArrayOf(0.0)) val res = tensor.transposed(0, 0) assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(0.0)) - assertTrue(res.shape contentEquals Shape(1)) + assertTrue(res.shape contentEquals ShapeND(1)) } @Test fun testTranspose3x2() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = fromArray(ShapeND(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transposed(1, 0) assertTrue(res.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) - assertTrue(res.shape contentEquals Shape(2, 3)) + assertTrue(res.shape contentEquals ShapeND(2, 3)) } @Test fun testTranspose1x2x3() = DoubleTensorAlgebra { - val tensor = fromArray(Shape(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = fromArray(ShapeND(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transposed(0, 1) val res02 = tensor.transposed(-3, 2) val res12 = tensor.transposed() - assertTrue(res01.shape contentEquals Shape(2, 1, 3)) - assertTrue(res02.shape contentEquals Shape(3, 2, 1)) - assertTrue(res12.shape contentEquals Shape(1, 3, 2)) + assertTrue(res01.shape contentEquals ShapeND(2, 1, 3)) + assertTrue(res02.shape contentEquals ShapeND(3, 2, 1)) + assertTrue(res12.shape contentEquals ShapeND(1, 3, 2)) assertTrue(res01.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(res02.asDoubleTensor().source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) @@ -75,7 +75,7 @@ internal class TestDoubleTensorAlgebra { @Test fun testLinearStructure() = DoubleTensorAlgebra { - val shape = Shape(3) + val shape = ShapeND(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) val tensorC = full(value = 789.3, shape = shape) @@ -107,28 +107,28 @@ internal class TestDoubleTensorAlgebra { @Test fun testDot() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor11 = fromArray(Shape(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = fromArray(Shape(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) - val tensor4 = fromArray(Shape(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) - val tensor5 = fromArray(Shape(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor11 = fromArray(ShapeND(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(ShapeND(1, 1, 3), doubleArrayOf(-1.0, -2.0, -3.0)) + val tensor4 = fromArray(ShapeND(2, 3, 3), (1..18).map { it.toDouble() }.toDoubleArray()) + val tensor5 = fromArray(ShapeND(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) val res12 = tensor1.dot(tensor2) assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0)) - assertTrue(res12.shape contentEquals Shape(2)) + assertTrue(res12.shape contentEquals ShapeND(2)) val res32 = tensor3.matmul(tensor2) assertTrue(res32.source contentEquals doubleArrayOf(-140.0)) - assertTrue(res32.shape contentEquals Shape(1, 1)) + assertTrue(res32.shape contentEquals ShapeND(1, 1)) val res22 = tensor2.dot(tensor2) assertTrue(res22.source contentEquals doubleArrayOf(1400.0)) - assertTrue(res22.shape contentEquals Shape(1)) + assertTrue(res22.shape contentEquals ShapeND(1)) val res11 = tensor1.dot(tensor11) assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) - assertTrue(res11.shape contentEquals Shape(2, 2)) + assertTrue(res11.shape contentEquals ShapeND(2, 2)) val res45 = tensor4.matmul(tensor5) assertTrue( @@ -137,44 +137,44 @@ internal class TestDoubleTensorAlgebra { 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 ) ) - assertTrue(res45.shape contentEquals Shape(2, 3, 3)) + assertTrue(res45.shape contentEquals ShapeND(2, 3, 3)) } @Test fun testDiagonalEmbedding() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor3 = zeros(Shape(2, 3, 4, 5)) + val tensor1 = fromArray(ShapeND(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = zeros(ShapeND(2, 3, 4, 5)) assertTrue( diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals - Shape(2, 3, 4, 5, 5) + ShapeND(2, 3, 4, 5, 5) ) assertTrue( diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals - Shape(2, 3, 4, 6, 6) + ShapeND(2, 3, 4, 6, 6) ) assertTrue( diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals - Shape(7, 2, 3, 7, 4) + ShapeND(7, 2, 3, 7, 4) ) val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) - assertTrue(diagonal1.shape contentEquals Shape(3, 3)) + assertTrue(diagonal1.shape contentEquals ShapeND(3, 3)) 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 Shape(4, 4)) + assertTrue(diagonal1Offset.shape contentEquals ShapeND(4, 4)) 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 Shape(4, 2, 4)) + assertTrue(diagonal2.shape contentEquals ShapeND(4, 2, 4)) assertTrue( diagonal2.source contentEquals doubleArrayOf( @@ -188,9 +188,9 @@ internal class TestDoubleTensorAlgebra { @Test fun testEq() = DoubleTensorAlgebra { - val tensor1 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor3 = fromArray(Shape(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) + val tensor1 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = fromArray(ShapeND(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) assertTrue(tensor1 eq tensor1) assertTrue(tensor1 eq tensor2) @@ -204,7 +204,7 @@ internal class TestDoubleTensorAlgebra { val l = tensor.getTensor(0).map { it + 1.0 } val r = tensor.getTensor(1).map { it - 1.0 } val res = l + r - assertTrue { Shape(5, 5) contentEquals res.shape } + assertTrue { ShapeND(5, 5) contentEquals res.shape } assertEquals(2.0, res[4, 4]) } } 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 5ac1c74a3..8533c9d32 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 @@ -33,7 +33,7 @@ public open class ViktorFieldOpsND : override val elementAlgebra: DoubleField get() = DoubleField @OptIn(UnsafeKMathAPI::class) - override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = + override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = F64Array(*shape.asArray()).apply { ColumnStrides(shape).asSequence().forEach { index -> set(value = DoubleField.initializer(index), indices = index) @@ -46,7 +46,7 @@ public open class ViktorFieldOpsND : @PerformancePitfall override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = F64Array(*shape.asArray()).apply { - ColumnStrides(Shape(shape)).asSequence().forEach { index -> + ColumnStrides(ShapeND(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(this@map[index]), indices = index) } }.asStructure() @@ -56,7 +56,7 @@ public open class ViktorFieldOpsND : override fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): ViktorStructureND = F64Array(*shape.asArray()).apply { - ColumnStrides(Shape(shape)).asSequence().forEach { index -> + ColumnStrides(ShapeND(shape)).asSequence().forEach { index -> set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) } }.asStructure() @@ -127,7 +127,7 @@ public open class ViktorFieldND( private val shapeAsArray: IntArray, ) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { - override val shape: Shape = Shape(shapeAsArray) + override val shape: ShapeND = ShapeND(shapeAsArray) override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shapeAsArray).asStructure() } 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 cee52b06d..085790355 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 @@ -9,11 +9,11 @@ import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.MutableStructureND -import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.ShapeND @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { - override val shape: Shape get() = Shape(f64Buffer.shape) + override val shape: ShapeND get() = ShapeND(f64Buffer.shape) @OptIn(PerformancePitfall::class) override inline fun get(index: IntArray): Double = f64Buffer.get(*index) From e24463c58bc6368709c2db681f9d1b8518f36f7d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 15 Oct 2022 18:45:06 +0300 Subject: [PATCH 14/72] Refactor Dubins path --- build.gradle.kts | 2 +- .../kmath/tensorflow/TensorFlowAlgebra.kt | 3 + .../kscience/kmath/trajectory/DubinsPath.kt | 177 +++++++++--------- .../kscience/kmath/trajectory/DubinsPose2D.kt | 36 ++++ .../space/kscience/kmath/trajectory/Pose2D.kt | 33 ---- .../{Trajectory.kt => Trajectory2D.kt} | 64 ++++--- .../kmath/trajectory/TrajectoryCost.kt | 14 -- .../space/kscience/kmath/trajectory/route.kt | 4 +- .../space/kscience/kmath/trajectory/Math.kt | 12 +- .../kmath/trajectory/dubins/DubinsTests.kt | 18 +- .../kmath/trajectory/segments/ArcTests.kt | 8 +- .../kmath/trajectory/segments/LineTests.kt | 22 +-- 12 files changed, 201 insertions(+), 192 deletions(-) create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt rename kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/{Trajectory.kt => Trajectory2D.kt} (53%) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt diff --git a/build.gradle.kts b/build.gradle.kts index c7e2e5892..bf732c893 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-5" + version = "0.3.1-dev-6" } subprojects { 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 435b01b80..bc5fb9616 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 @@ -77,11 +77,13 @@ public abstract class TensorFlowOutput( } } + @PerformancePitfall override fun get(index: IntArray): T = actualTensor[index] @PerformancePitfall override fun elements(): Sequence> = actualTensor.elements() + @PerformancePitfall override fun set(index: IntArray, value: T) { actualTensor[index] = value } @@ -101,6 +103,7 @@ public abstract class TensorFlowAlgebra> internal c protected abstract fun const(value: T): Constant + @OptIn(PerformancePitfall::class) override fun StructureND.valueOrNull(): T? = if (shape contentEquals ShapeND(1)) get(intArrayOf(0)) else null 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 index 6a340f6b9..1ba9936ee 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -13,75 +13,80 @@ import kotlin.math.acos import kotlin.math.cos import kotlin.math.sin -internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first +internal fun DubinsPose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first -internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second +internal fun DubinsPose2D.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) +internal fun DubinsPose2D.getTangentCircles(radius: Double): Pair = with(Euclidean2DSpace) { + val dX = radius * cos(bearing) + val dY = radius * sin(bearing) return Circle2D(vector(x - dX, y + dY), radius) to Circle2D(vector(x + dX, y - dY), radius) } -internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory = outerTangent(a, b, CircleTrajectory.Direction.LEFT) +internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory2D = + outerTangent(a, b, CircleTrajectory2D.Direction.LEFT) -internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory = outerTangent(a, b, - CircleTrajectory.Direction.RIGHT +internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightTrajectory2D = outerTangent( + a, b, + CircleTrajectory2D.Direction.RIGHT ) -private fun outerTangent(a: Circle2D, b: Circle2D, side: CircleTrajectory.Direction): StraightTrajectory = with(Euclidean2DSpace){ - val centers = StraightTrajectory(a.center, b.center) - val p1 = when (side) { - CircleTrajectory.Direction.LEFT -> vector( - a.center.x - a.radius * cos(centers.theta), - a.center.y + a.radius * sin(centers.theta) - ) - CircleTrajectory.Direction.RIGHT -> vector( - a.center.x + a.radius * cos(centers.theta), - a.center.y - a.radius * sin(centers.theta) +private fun outerTangent(a: Circle2D, b: Circle2D, side: CircleTrajectory2D.Direction): StraightTrajectory2D = + with(Euclidean2DSpace) { + val centers = StraightTrajectory2D(a.center, b.center) + val p1 = when (side) { + CircleTrajectory2D.Direction.LEFT -> vector( + a.center.x - a.radius * cos(centers.bearing), + a.center.y + a.radius * sin(centers.bearing) + ) + + CircleTrajectory2D.Direction.RIGHT -> vector( + a.center.x + a.radius * cos(centers.bearing), + a.center.y - a.radius * sin(centers.bearing) + ) + } + return StraightTrajectory2D( + p1, + vector(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) ) } - return StraightTrajectory( - 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): StraightTrajectory? = - innerTangent(base, direction, CircleTrajectory.Direction.LEFT) +internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory2D? = + innerTangent(base, direction, CircleTrajectory2D.Direction.LEFT) -internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory? = - innerTangent(base, direction, CircleTrajectory.Direction.RIGHT) +internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory2D? = + innerTangent(base, direction, CircleTrajectory2D.Direction.RIGHT) -private fun innerTangent(base: Circle2D, direction: Circle2D, side: CircleTrajectory.Direction): StraightTrajectory? = with(Euclidean2DSpace){ - val centers = StraightTrajectory(base.center, direction.center) - if (centers.length < base.radius * 2) return null - val angle = theta( - when (side) { - CircleTrajectory.Direction.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) - CircleTrajectory.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 StraightTrajectory(p1, p2) -} +private fun innerTangent(base: Circle2D, direction: Circle2D, side: CircleTrajectory2D.Direction): StraightTrajectory2D? = + with(Euclidean2DSpace) { + val centers = StraightTrajectory2D(base.center, direction.center) + if (centers.length < base.radius * 2) return null + val angle = theta( + when (side) { + CircleTrajectory2D.Direction.LEFT -> centers.bearing + acos(base.radius * 2 / centers.length) + CircleTrajectory2D.Direction.RIGHT -> centers.bearing - 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 StraightTrajectory2D(p1, p2) + } internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) @Suppress("DuplicatedCode") public class DubinsPath( - public val a: CircleTrajectory, - public val b: Trajectory, - public val c: CircleTrajectory, -) : CompositeTrajectory(listOf(a,b,c)) { + public val a: CircleTrajectory2D, + public val b: Trajectory2D, + public val c: CircleTrajectory2D, +) : CompositeTrajectory2D(listOf(a, b, c)) { public val type: TYPE = TYPE.valueOf( arrayOf( a.direction.name[0], - if (b is CircleTrajectory) b.direction.name[0] else 'S', + if (b is CircleTrajectory2D) b.direction.name[0] else 'S', c.direction.name[0] ).toCharArray().concatToString() ) @@ -92,8 +97,8 @@ public class DubinsPath( public companion object { public fun all( - start: Pose2D, - end: Pose2D, + start: DubinsPose2D, + end: DubinsPose2D, turningRadius: Double, ): List = listOfNotNull( rlr(start, end, turningRadius), @@ -104,132 +109,132 @@ public class DubinsPath( lsr(start, end, turningRadius) ) - public fun shortest(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath = + public fun shortest(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath = all(start, end, turningRadius).minBy { it.length } - public fun rlr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { + public fun rlr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) - val centers = StraightTrajectory(c1.center, c2.center) + val centers = StraightTrajectory2D(c1.center, c2.center) if (centers.length > turningRadius * 4) return null val firstVariant = run { - var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) + var theta = theta(centers.bearing - 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))) + theta = theta(centers.bearing + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.RIGHT) - val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.LEFT) - val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) DubinsPath(a1, a2, a3) } val secondVariant = run { - var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) + var theta = theta(centers.bearing + 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))) + theta = theta(centers.bearing - 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.RIGHT) - val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.LEFT) - val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) DubinsPath(a1, a2, a3) } return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } - public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { + public fun lrl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) - val centers = StraightTrajectory(c1.center, c2.center) + val centers = StraightTrajectory2D(c1.center, c2.center) if (centers.length > turningRadius * 4) return null val firstVariant = run { - var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) + var theta = theta(centers.bearing + 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))) + theta = theta(centers.bearing - 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.LEFT) - val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.RIGHT) - val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) DubinsPath(a1, a2, a3) } val secondVariant = run{ - var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) + var theta = theta(centers.bearing - 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))) + theta = theta(centers.bearing + 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 = CircleTrajectory.of(c1.center, start, p1, CircleTrajectory.Direction.LEFT) - val a2 = CircleTrajectory.of(e.center, p1, p2, CircleTrajectory.Direction.RIGHT) - val a3 = CircleTrajectory.of(c2.center, p2, end, CircleTrajectory.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) DubinsPath(a1, a2, a3) } return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } - public fun rsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + public fun rsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = leftOuterTangent(c1, c2) - val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.RIGHT) - val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) return DubinsPath(a1, s, a3) } - public fun lsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + public fun lsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = rightOuterTangent(c1, c2) - val a1 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.LEFT) - val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) return DubinsPath(a1, s, a3) } - public fun rsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + public fun rsl(start: DubinsPose2D, end: DubinsPose2D, 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 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.RIGHT) - val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) return DubinsPath(a1, s, a3) } - public fun lsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + public fun lsr(start: DubinsPose2D, end: DubinsPose2D, 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 = CircleTrajectory.of(c1.center, start, s.start, CircleTrajectory.Direction.LEFT) - val a3 = CircleTrajectory.of(c2.center, s.end, end, CircleTrajectory.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) return DubinsPath(a1, s, a3) } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt new file mode 100644 index 000000000..ba001b4a5 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2018-2022 KMath 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 (clockwise from positive y-axis direction) + */ +public interface DubinsPose2D : DoubleVector2D { + public val coordinate: DoubleVector2D + public val bearing: Double +} + +public class PhaseVector2D( + override val coordinate: DoubleVector2D, + public val velocity: DoubleVector2D, +) : DubinsPose2D, DoubleVector2D by coordinate { + override val bearing: Double get() = atan2(velocity.x, velocity.y) +} + +internal class Pose2DImpl( + override val coordinate: DoubleVector2D, + override val bearing: Double, +) : DubinsPose2D, DoubleVector2D by coordinate{ + + override fun toString(): String = "Pose2D(x=$x, y=$y, bearing=$bearing)" +} + + +public fun Pose2D(coordinate: DoubleVector2D, theta: Double): DubinsPose2D = Pose2DImpl(coordinate, theta) \ 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 deleted file mode 100644 index 788cf57af..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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/Trajectory2D.kt similarity index 53% rename from kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt rename to kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 1085f7847..f1ae20722 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -8,58 +8,61 @@ 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 sealed interface Trajectory2D { public val length: Double } /** * Straight path segment. The order of start and end defines the direction */ -public data class StraightTrajectory( +public data class StraightTrajectory2D( internal val start: DoubleVector2D, internal val end: DoubleVector2D, -) : Trajectory { +) : Trajectory2D { override val length: Double get() = start.distanceTo(end) - internal val theta: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) + internal val bearing: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) } /** * An arc segment */ -public data class CircleTrajectory( +public data class CircleTrajectory2D( public val circle: Circle2D, - public val start: Pose2D, - public val end: Pose2D, -) : Trajectory { + public val start: DubinsPose2D, + public val end: DubinsPose2D, +) : Trajectory2D { public enum class Direction { LEFT, RIGHT } - override val length: Double by lazy { - val angle: Double = theta( + /** + * Arc length in radians + */ + val arcLength: Double + get() = theta( if (direction == Direction.LEFT) { - start.theta - end.theta + start.bearing - end.bearing } else { - end.theta - start.theta + end.bearing - start.bearing } ) - val proportion = angle / (2 * PI) - circle.circumference * proportion + + override val length: Double by lazy { + circle.radius * arcLength } internal val direction: Direction by lazy { if (start.y < circle.center.y) { - if (start.theta > PI) Direction.RIGHT else Direction.LEFT + if (start.bearing > PI) Direction.RIGHT else Direction.LEFT } else if (start.y > circle.center.y) { - if (start.theta < PI) Direction.RIGHT else Direction.LEFT + if (start.bearing < PI) Direction.RIGHT else Direction.LEFT } else { - if (start.theta == 0.0) { + if (start.bearing == 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 @@ -68,12 +71,17 @@ public data class CircleTrajectory( } public companion object { - public fun of(center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, direction: Direction): CircleTrajectory { + public fun of( + center: DoubleVector2D, + start: DoubleVector2D, + end: DoubleVector2D, + direction: Direction, + ): CircleTrajectory2D { fun calculatePose( vector: DoubleVector2D, theta: Double, direction: Direction, - ): Pose2D = Pose2D( + ): DubinsPose2D = Pose2D( vector, when (direction) { Direction.LEFT -> theta(theta - PI / 2) @@ -81,16 +89,20 @@ public data class CircleTrajectory( } ) - val s1 = StraightTrajectory(center, start) - val s2 = StraightTrajectory(center, end) - val pose1 = calculatePose(start, s1.theta, direction) - val pose2 = calculatePose(end, s2.theta, direction) - return CircleTrajectory(Circle2D(center, s1.length), pose1, pose2) + val s1 = StraightTrajectory2D(center, start) + val s2 = StraightTrajectory2D(center, end) + val pose1 = calculatePose(start, s1.bearing, direction) + val pose2 = calculatePose(end, s2.bearing, direction) + val trajectory = CircleTrajectory2D(Circle2D(center, s1.length), pose1, pose2) + if(trajectory.direction != direction){ + error("Trajectory direction mismatch") + } + return trajectory } } } -public open class CompositeTrajectory(public val segments: Collection) : Trajectory { +public open class CompositeTrajectory2D(public val segments: Collection) : Trajectory2D { 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 deleted file mode 100644 index 3782a9a32..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 index 2e8e43be9..56350835d 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt @@ -12,5 +12,5 @@ public fun interface MaxCurvature { public fun DubinsPath.Companion.shortest( start: PhaseVector2D, end: PhaseVector2D, - computer: MaxCurvature, -): DubinsPath = shortest(start, end, computer.compute(start)) + maxCurvature: MaxCurvature, +): DubinsPath = shortest(start, end, maxCurvature.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 index 64513f6e2..4599f30f8 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt @@ -15,14 +15,14 @@ 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 DubinsPose2D.equalsFloat(other: DubinsPose2D) = x.equalFloat(other.x) && y.equalFloat(other.y) && bearing.equalFloat(other.bearing) -fun StraightTrajectory.inverse() = StraightTrajectory(end, start) -fun StraightTrajectory.shift(shift: Int, width: Double): StraightTrajectory = with(Euclidean2DSpace){ - val dX = width * sin(inverse().theta) - val dY = width * sin(theta) +fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, start) +fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace){ + val dX = width * sin(inverse().bearing) + val dY = width * sin(bearing) - return StraightTrajectory( + return StraightTrajectory2D( 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 index b545b7c94..8cea22b45 100644 --- 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 @@ -16,11 +16,11 @@ class DubinsTests { @Test fun dubinsTest() = with(Euclidean2DSpace){ - val straight = StraightTrajectory(vector(0.0, 0.0), vector(100.0, 100.0)) + val straight = StraightTrajectory2D(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 start = Pose2D(straight.end, straight.bearing) + val end = Pose2D(lineP1.start, lineP1.bearing) val radius = 2.0 val dubins = DubinsPath.all(start, end, radius) @@ -45,14 +45,14 @@ class DubinsTests { assertTrue(end.equalsFloat(path.c.end)) // Not working, theta double precision inaccuracy - if (path.b is CircleTrajectory) { - val b = path.b as CircleTrajectory + if (path.b is CircleTrajectory2D) { + val b = path.b as CircleTrajectory2D assertTrue(path.a.end.equalsFloat(b.start)) assertTrue(path.c.start.equalsFloat(b.end)) - } else if (path.b is StraightTrajectory) { - val b = path.b as StraightTrajectory - assertTrue(path.a.end.equalsFloat(Pose2D(b.start, b.theta))) - assertTrue(path.c.start.equalsFloat(Pose2D(b.end, b.theta))) + } else if (path.b is StraightTrajectory2D) { + val b = path.b as StraightTrajectory2D + assertTrue(path.a.end.equalsFloat(Pose2D(b.start, b.bearing))) + assertTrue(path.c.start.equalsFloat(Pose2D(b.end, b.bearing))) } } } 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 index 17277c35e..af1444ade 100644 --- 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 @@ -8,7 +8,7 @@ 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.CircleTrajectory +import space.kscience.kmath.trajectory.CircleTrajectory2D import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.test.Test import kotlin.test.assertEquals @@ -18,9 +18,9 @@ class ArcTests { @Test fun arcTest() = with(Euclidean2DSpace){ val circle = Circle2D(vector(0.0, 0.0), 2.0) - val arc = CircleTrajectory.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), CircleTrajectory.Direction.RIGHT) + val arc = CircleTrajectory2D.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), CircleTrajectory2D.Direction.RIGHT) assertEquals(circle.circumference / 4, arc.length, 1.0) - assertEquals(0.0, arc.start.theta.radiansToDegrees()) - assertEquals(90.0, arc.end.theta.radiansToDegrees()) + assertEquals(0.0, arc.start.bearing.radiansToDegrees()) + assertEquals(90.0, arc.end.bearing.radiansToDegrees()) } } 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 index 4b54d775c..03320a3df 100644 --- 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.trajectory.StraightTrajectory +import space.kscience.kmath.trajectory.StraightTrajectory2D import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow import kotlin.math.sqrt @@ -17,21 +17,21 @@ class LineTests { @Test fun lineTest() = with(Euclidean2DSpace){ - val straight = StraightTrajectory(vector(0.0, 0.0), vector(100.0, 100.0)) + val straight = StraightTrajectory2D(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()) + assertEquals(45.0, straight.bearing.radiansToDegrees()) } @Test fun lineAngleTest() = with(Euclidean2DSpace){ //val zero = Vector2D(0.0, 0.0) - val north = StraightTrajectory(Euclidean2DSpace.zero, vector(0.0, 2.0)) - assertEquals(0.0, north.theta.radiansToDegrees()) - val east = StraightTrajectory(Euclidean2DSpace.zero, vector(2.0, 0.0)) - assertEquals(90.0, east.theta.radiansToDegrees()) - val south = StraightTrajectory(Euclidean2DSpace.zero, vector(0.0, -2.0)) - assertEquals(180.0, south.theta.radiansToDegrees()) - val west = StraightTrajectory(Euclidean2DSpace.zero, vector(-2.0, 0.0)) - assertEquals(270.0, west.theta.radiansToDegrees()) + val north = StraightTrajectory2D(zero, vector(0.0, 2.0)) + assertEquals(0.0, north.bearing.radiansToDegrees()) + val east = StraightTrajectory2D(zero, vector(2.0, 0.0)) + assertEquals(90.0, east.bearing.radiansToDegrees()) + val south = StraightTrajectory2D(zero, vector(0.0, -2.0)) + assertEquals(180.0, south.bearing.radiansToDegrees()) + val west = StraightTrajectory2D(zero, vector(-2.0, 0.0)) + assertEquals(270.0, west.bearing.radiansToDegrees()) } } From fb0d016aa824227b2b76f102525584426ad1e48a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 15 Oct 2022 18:58:30 +0300 Subject: [PATCH 15/72] Perform merge build only on JVM --- .github/workflows/build.yml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cffef64b0..20d5f9a68 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,26 +7,18 @@ on: jobs: build: - strategy: - matrix: - os: [ macOS-latest, windows-latest ] - runs-on: ${{matrix.os}} - timeout-minutes: 40 + runs-on: windows-latest + timeout-minutes: 20 steps: - - uses: actions/checkout@v3.0.0 - - uses: actions/setup-java@v3.0.0 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3.5.1 with: - java-version: 11 - distribution: liberica - - name: Cache konan - uses: actions/cache@v3.0.1 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- + java-version: '11' + distribution: 'liberica' + cache: 'gradle' - name: Gradle Wrapper Validation uses: gradle/wrapper-validation-action@v1.0.4 - - uses: gradle/gradle-build-action@v2.1.5 + - name: Gradle Build + uses: gradle/gradle-build-action@v2.3.2 with: - arguments: build + arguments: test jvmTest From 94489b28e254f0f3c5c95c1b8a63588e3a390838 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 Oct 2022 14:41:48 +0300 Subject: [PATCH 16/72] Fix visibility in Trajectory2D --- build.gradle.kts | 12 ++++++------ docs/templates/ARTIFACT-TEMPLATE.md | 6 +++++- .../space/kscience/kmath/trajectory/DubinsPose2D.kt | 4 ++-- .../space/kscience/kmath/trajectory/Trajectory2D.kt | 10 +++++----- .../kscience/kmath/trajectory/dubins/DubinsTests.kt | 8 ++++---- .../kscience/kmath/trajectory/{Math.kt => math.kt} | 0 6 files changed, 22 insertions(+), 18 deletions(-) rename kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/{Math.kt => math.kt} (100%) diff --git a/build.gradle.kts b/build.gradle.kts index bf732c893..92379d915 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ +import space.kscience.gradle.isInDevelopment import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useSPCTeam @@ -77,12 +78,11 @@ ksciencePublish { } github("kmath", "SciProgCentre") space( - "https://maven.pkg.jetbrains.space/spc/p/sci/maven" -// if (isInDevelopment) { -// "https://maven.pkg.jetbrains.space/spc/p/sci/dev" -// } else { -// "https://maven.pkg.jetbrains.space/spc/p/sci/release" -// } + if (isInDevelopment) { + "https://maven.pkg.jetbrains.space/spc/p/sci/dev" + } else { + "https://maven.pkg.jetbrains.space/spc/p/sci/maven" + } ) sonatype() } diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 1bac2a8ff..a3e47e693 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -3,10 +3,12 @@ The Maven coordinates of this project are `${group}:${name}:${version}`. **Gradle:** -```gradle +```groovy repositories { maven { url 'https://repo.kotlin.link' } mavenCentral() + // development and snapshot versions + maven { url 'https://maven.pkg.jetbrains.space/spc/p/sci/dev' } } dependencies { @@ -18,6 +20,8 @@ dependencies { repositories { maven("https://repo.kotlin.link") mavenCentral() + // development and snapshot versions + maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") } dependencies { diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt index ba001b4a5..5aa8c1455 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt @@ -24,7 +24,7 @@ public class PhaseVector2D( override val bearing: Double get() = atan2(velocity.x, velocity.y) } -internal class Pose2DImpl( +private class DubinsPose2DImpl( override val coordinate: DoubleVector2D, override val bearing: Double, ) : DubinsPose2D, DoubleVector2D by coordinate{ @@ -33,4 +33,4 @@ internal class Pose2DImpl( } -public fun Pose2D(coordinate: DoubleVector2D, theta: Double): DubinsPose2D = Pose2DImpl(coordinate, theta) \ No newline at end of file +public fun DubinsPose2D(coordinate: DoubleVector2D, theta: Double): DubinsPose2D = DubinsPose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index f1ae20722..3fcf4365d 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -19,12 +19,12 @@ public sealed interface Trajectory2D { * Straight path segment. The order of start and end defines the direction */ public data class StraightTrajectory2D( - internal val start: DoubleVector2D, - internal val end: DoubleVector2D, + public val start: DoubleVector2D, + public val end: DoubleVector2D, ) : Trajectory2D { override val length: Double get() = start.distanceTo(end) - internal val bearing: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) + public val bearing: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) } /** @@ -56,7 +56,7 @@ public data class CircleTrajectory2D( circle.radius * arcLength } - internal val direction: Direction by lazy { + public val direction: Direction by lazy { if (start.y < circle.center.y) { if (start.bearing > PI) Direction.RIGHT else Direction.LEFT } else if (start.y > circle.center.y) { @@ -81,7 +81,7 @@ public data class CircleTrajectory2D( vector: DoubleVector2D, theta: Double, direction: Direction, - ): DubinsPose2D = Pose2D( + ): DubinsPose2D = DubinsPose2D( vector, when (direction) { Direction.LEFT -> theta(theta - PI / 2) 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 index 8cea22b45..5bbf8c294 100644 --- 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 @@ -19,8 +19,8 @@ class DubinsTests { val straight = StraightTrajectory2D(vector(0.0, 0.0), vector(100.0, 100.0)) val lineP1 = straight.shift(1, 10.0).inverse() - val start = Pose2D(straight.end, straight.bearing) - val end = Pose2D(lineP1.start, lineP1.bearing) + val start = DubinsPose2D(straight.end, straight.bearing) + val end = DubinsPose2D(lineP1.start, lineP1.bearing) val radius = 2.0 val dubins = DubinsPath.all(start, end, radius) @@ -51,8 +51,8 @@ class DubinsTests { assertTrue(path.c.start.equalsFloat(b.end)) } else if (path.b is StraightTrajectory2D) { val b = path.b as StraightTrajectory2D - assertTrue(path.a.end.equalsFloat(Pose2D(b.start, b.bearing))) - assertTrue(path.c.start.equalsFloat(Pose2D(b.end, b.bearing))) + assertTrue(path.a.end.equalsFloat(DubinsPose2D(b.start, b.bearing))) + assertTrue(path.c.start.equalsFloat(DubinsPose2D(b.end, b.bearing))) } } } 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 similarity index 100% rename from kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt rename to kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt From 8286db30afef0fb5e647117fd7892f20ebfc1e73 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 Oct 2022 20:15:37 +0300 Subject: [PATCH 17/72] Optimize tensor shape computation --- .../space/kscience/kmath/nd/ShapeIndices.kt | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt index 37e0c7b5e..3a27614c5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndices.kt @@ -51,10 +51,15 @@ public abstract class Strides : ShapeIndexer { */ internal abstract val strides: IntArray - public override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value !in 0 until shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0, ${this.shape[i]})") - value * strides[i] - }.sum() + public override fun offset(index: IntArray): Int { + var res = 0 + index.forEachIndexed { i, value -> + if (value !in 0 until shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0, ${this.shape[i]})") + res += value * strides[i] + + } + return res + } // TODO introduce a fast way to calculate index of the next element? @@ -74,17 +79,15 @@ public class ColumnStrides(override val shape: ShapeND) : Strides() { /** * Strides for memory access */ - override val strides: IntArray by lazy { - sequence { - var current = 1 - yield(1) + override val strides: IntArray = sequence { + var current = 1 + yield(1) - shape.forEach { - current *= it - yield(current) - } - }.toList().toIntArray() - } + shape.forEach { + current *= it + yield(current) + } + }.toList().toIntArray() override fun index(offset: Int): IntArray { val res = IntArray(shape.size) @@ -120,10 +123,10 @@ public class ColumnStrides(override val shape: ShapeND) : Strides() { */ public class RowStrides(override val shape: ShapeND) : Strides() { - override val strides: IntArray by lazy { + override val strides: IntArray = run { val nDim = shape.size val res = IntArray(nDim) - if (nDim == 0) return@lazy res + if (nDim == 0) return@run res var current = nDim - 1 res[current] = 1 From cff563c321fba4c5fe9be3660d504079acfdc746 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 5 Nov 2022 16:14:23 +0300 Subject: [PATCH 18/72] Major tensor refactoring --- CHANGELOG.md | 3 + .../benchmarks/TensorAlgebraBenchmark.kt | 6 +- build.gradle.kts | 2 +- .../structures/StructureWriteBenchmark.kt | 11 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 11 +- .../space/kscience/kmath/tensors/PCA.kt | 21 +- .../kmath/tensors/dataSetNormalization.kt | 11 +- .../tensors/linearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/neuralNetwork.kt | 12 +- gradle.properties | 4 + .../commons/optimization/OptimizeTest.kt | 3 +- .../kscience/kmath/expressions/DSAlgebra.kt | 4 +- .../kmath/expressions/specialExpressions.kt | 2 + .../kmath/operations/DoubleBufferField.kt | 105 +--- .../kmath/operations/DoubleBufferOps.kt | 110 ++-- .../kmath/operations/algebraExtensions.kt | 28 +- .../kscience/kmath/structures/DoubleBuffer.kt | 3 + .../kmath/structures/bufferExtensions.kt | 50 +- .../space/kscience/kmath/structures/types.kt | 20 + .../kmath/coroutines/coroutinesExtra.kt | 4 +- .../integration/GaussIntegratorRuleFactory.kt | 6 +- .../kmath/integration/SplineIntegrator.kt | 6 +- .../histogram/UniformHistogramGroupND.kt | 2 +- .../kscience/kmath/multik/MultikNDTest.kt | 1 + .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 56 +- .../tmp/minuit/HessianGradientCalculator.kt | 2 +- .../src/commonMain/tmp/minuit/MnPosDef.kt | 10 +- .../kotlin/space/kscience/kmath/stat/Mean.kt | 12 +- .../kscience/kmath/stat/StatisticTest.kt | 17 +- .../kmath/tensorflow/DoubleTensorFlowOps.kt | 1 + .../tensors/api/AnalyticTensorAlgebra.kt | 81 +-- .../tensors/api/LinearOpsTensorAlgebra.kt | 10 +- .../kmath/tensors/core/DoubleTensor.kt | 61 +-- .../kmath/tensors/core/DoubleTensor1D.kt | 45 ++ .../kmath/tensors/core/DoubleTensor2D.kt | 71 +++ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 490 +++--------------- .../kmath/tensors/core/internal/checks.kt | 7 +- .../kmath/tensors/core/internal/linUtils.kt | 8 +- .../kscience/kmath/tensors/core/tensorOps.kt | 370 +++++++++++++ .../core/TestDoubleAnalyticTensorAlgebra.kt | 34 +- .../core/TestDoubleLinearOpsAlgebra.kt | 16 +- 41 files changed, 897 insertions(+), 821 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/types.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor1D.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor2D.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorOps.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index eea1dd3ea..c31740a31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,14 @@ ## [Unreleased] ### Added +- Type-aliases for numbers like `Float64` - 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 +- Tensor operations switched to prefix notation +- Row-wise and column-wise ND shapes in the core - Shape is read-only - Major refactor of tensors (only minor API changes) - Kotlin 1.7.20 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 3ed7163b3..c4382374a 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt @@ -13,6 +13,8 @@ import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.linear.matrix import space.kscience.kmath.linear.symmetric import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.tensors.core.symEigJacobi +import space.kscience.kmath.tensors.core.symEigSvd import space.kscience.kmath.tensors.core.tensorAlgebra import kotlin.random.Random @@ -27,11 +29,11 @@ internal class TensorAlgebraBenchmark { @Benchmark fun tensorSymEigSvd(blackhole: Blackhole) = with(Double.tensorAlgebra) { - blackhole.consume(matrix.symEigSvd(1e-10)) + blackhole.consume(symEigSvd(matrix, 1e-10)) } @Benchmark fun tensorSymEigJacobi(blackhole: Blackhole) = with(Double.tensorAlgebra) { - blackhole.consume(matrix.symEigJacobi(50, 1e-10)) + blackhole.consume(symEigJacobi(matrix, 50, 1e-10)) } } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 92379d915..e03bec9af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-6" + version = "0.3.1-dev-7" } subprojects { 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 522eeb768..14c058417 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -8,17 +8,20 @@ package space.kscience.kmath.structures import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.operations.map +import space.kscience.kmath.operations.mapToBuffer import kotlin.system.measureTimeMillis -private inline fun BufferND.map(block: (T) -> R): BufferND = BufferND(indices, buffer.map(block)) +private inline fun BufferND.mapToBufferND( + bufferFactory: BufferFactory = BufferFactory.auto(), + crossinline block: (T) -> R, +): BufferND = BufferND(indices, buffer.mapToBuffer(bufferFactory, block)) @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 1.0 } - structure.map { it + 1 } // warm-up - val time1 = measureTimeMillis { val res = structure.map { it + 1 } } + structure.mapToBufferND { it + 1 } // warm-up + val time1 = measureTimeMillis { val res = structure.mapToBufferND { it + 1 } } println("Structure mapping finished in $time1 millis") val array = DoubleArray(n * n) { 1.0 } 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 40b927215..2c570ea34 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -5,18 +5,17 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra - +import space.kscience.kmath.tensors.core.randomNormal +import space.kscience.kmath.tensors.core.randomNormalLike import kotlin.math.abs // OLS estimator using SVD -@OptIn(PerformancePitfall::class) fun main() { //seed for random val randSeed = 100500L @@ -42,10 +41,10 @@ fun main() { // calculate y and add gaussian noise (N(0, 0.05)) val y = x dot alpha - y += y.randomNormalLike(randSeed) * 0.05 + y += randomNormalLike(y, randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD - val (u, singValues, v) = x.svd() + val (u, singValues, v) = svd(x) // we have to make sure the singular values of the matrix are not close to zero println("Singular values:\n$singValues") @@ -66,7 +65,7 @@ fun main() { require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - return diff.dot(diff).sqrt().value() + return sqrt(diff.dot(diff)).value() } println("MSE: ${mse(alpha, 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 78199aa8b..fb774a39d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -6,8 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.ShapeND -import space.kscience.kmath.tensors.core.tensorAlgebra -import space.kscience.kmath.tensors.core.withBroadcast +import space.kscience.kmath.tensors.core.* // simple PCA @@ -22,7 +21,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with ) // take y dependent on x with noise - val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5) + val y = 2.0 * x + (3.0 + randomNormalLike(x, seed) * 1.5) println("x:\n$x") println("y:\n$y") @@ -31,14 +30,14 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with val dataset = stack(listOf(x, y)).transposed() // normalize both x and y - val xMean = x.mean() - val yMean = y.mean() + val xMean = mean(x) + val yMean = mean(y) - val xStd = x.std() - val yStd = y.std() + val xStd = std(x) + val yStd = std(y) - val xScaled = (x - xMean) / xStd - val yScaled = (y - yMean) / yStd + val xScaled: DoubleTensor = (x - xMean) / xStd + val yScaled: DoubleTensor = (y - yMean) / yStd // save means ans standard deviations for further recovery val mean = fromArray( @@ -54,11 +53,11 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with println("Standard deviations:\n$std") // calculate the covariance matrix of scaled x and y - val covMatrix = cov(listOf(xScaled, yScaled)) + val covMatrix = covariance(listOf(xScaled.asDoubleTensor1D(), yScaled.asDoubleTensor1D())) println("Covariance matrix:\n$covMatrix") // and find out eigenvector of it - val (_, evecs) = covMatrix.symEig() + val (_, evecs) = symEig(covMatrix) val v = evecs.getTensor(0) println("Eigenvector:\n$v") 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 091889e8e..45c2ff120 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.ShapeND +import space.kscience.kmath.tensors.core.randomNormal import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.withBroadcast @@ -23,8 +24,8 @@ fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broad // find out mean and standard deviation of each column - val mean = dataset.mean(0, false) - val std = dataset.std(0, false) + val mean = mean(dataset, 0, false) + val std = std(dataset, 0, false) println("Mean:\n$mean") println("Standard deviation:\n$std") @@ -36,8 +37,8 @@ fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broad // now we can scale dataset with mean normalization val datasetScaled = (dataset - mean) / std - // find out mean and std of scaled dataset + // find out mean and standardDiviation of scaled dataset - println("Mean of scaled:\n${datasetScaled.mean(0, false)}") - println("Mean of scaled:\n${datasetScaled.std(0, false)}") + println("Mean of scaled:\n${mean(datasetScaled, 0, false)}") + println("Mean of scaled:\n${std(datasetScaled, 0, false)}") } \ No newline at end of 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 60716d0ba..238696cf9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -41,7 +41,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // solve `Ax = b` system using LUP decomposition // get P, L, U such that PA = LU - val (p, l, u) = a.lu() + val (p, l, u) = lu(a) // check P is permutation matrix println("P:\n$p") 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 52b3b556c..8fd5ae5ad 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -9,10 +9,7 @@ import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.contentEquals 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.toDoubleTensor +import space.kscience.kmath.tensors.core.* import kotlin.math.sqrt const val seed = 100500L @@ -51,7 +48,7 @@ fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { class ReLU : Activation(::relu, ::reluDer) fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { - 1.0 / (1.0 + (-x).exp()) + 1.0 / (1.0 + exp((-x))) } fun sigmoidDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { @@ -85,7 +82,7 @@ class Dense( val gradInput = outputError dot weights.transposed() val gradW = input.transposed() dot outputError - val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() + val gradBias = mean(structureND = outputError, dim = 0, keepDim = false) * input.shape[0].toDouble() weights -= learningRate * gradW bias -= learningRate * gradBias @@ -118,7 +115,7 @@ class NeuralNetwork(private val layers: List) { onesForAnswers[intArrayOf(index, label)] = 1.0 } - val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) + val softmaxValue = exp(yPred) / exp(yPred).sum(dim = 1, keepDim = true) (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } @@ -176,7 +173,6 @@ class NeuralNetwork(private val layers: List) { } -@OptIn(ExperimentalStdlibApi::class) fun main() = BroadcastDoubleTensorAlgebra { val features = 5 val sampleSize = 250 diff --git a/gradle.properties b/gradle.properties index 216ebf74a..da5867ea4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,3 +11,7 @@ org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m toolsVersion=0.13.1-kotlin-1.7.20 + + +org.gradle.parallel=true +org.gradle.workers.max=4 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 f6819a27f..7c8ba7d27 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 @@ -13,12 +13,11 @@ import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.y import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.map +import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.optimization.* import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer -import kotlin.math.pow import kotlin.test.Test internal class OptimizeTest { 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 index fa8bf5e58..e7ade4f66 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt @@ -268,7 +268,7 @@ public open class DSRing( 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) { + val newData: Buffer = data.mapToBuffer(valueBufferFactory) { algebra.block(it) } return DS(newData) @@ -276,7 +276,7 @@ public open class DSRing( 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) + val newData: Buffer = data.mapIndexedToBuffer(valueBufferFactory, block) return DS(newData) } 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 8cfa1b353..59dfeb8ea 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 @@ -11,6 +11,8 @@ import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.indices import kotlin.jvm.JvmName +//TODO move to stat + /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic * differentiation. 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 449730e7a..2e6b63a92 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 @@ -5,8 +5,6 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer @@ -32,9 +30,9 @@ public class DoubleBufferField(public val size: Int) : ExtendedField): DoubleBuffer = super.atanh(arg) override fun power(arg: Buffer, pow: Number): DoubleBuffer = if (pow.isInteger()) { - arg.mapInline { it.pow(pow.toInt()) } + arg.map { it.pow(pow.toInt()) } } else { - arg.mapInline { + arg.map { if(it<0) throw IllegalArgumentException("Negative argument $it could not be raised to the fractional power") it.pow(pow.toDouble()) } @@ -42,103 +40,4 @@ public class DoubleBufferField(public val size: Int) : ExtendedField) -> Buffer = super.unaryOperationFunction(operation) - - // override fun number(value: Number): Buffer = DoubleBuffer(size) { value.toDouble() } -// -// override fun Buffer.unaryMinus(): Buffer = DoubleBufferOperations.run { -// -this@unaryMinus -// } -// -// override fun add(a: Buffer, b: Buffer): DoubleBuffer { -// require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } -// return DoubleBufferOperations.add(a, b) -// } -// - -// -// override fun multiply(a: Buffer, b: Buffer): DoubleBuffer { -// require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } -// return DoubleBufferOperations.multiply(a, b) -// } -// -// override fun divide(a: Buffer, b: Buffer): DoubleBuffer { -// require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } -// return DoubleBufferOperations.divide(a, b) -// } -// -// override fun sin(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.sin(arg) -// } -// -// override fun cos(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.cos(arg) -// } -// -// override fun tan(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.tan(arg) -// } -// -// override fun asin(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.asin(arg) -// } -// -// override fun acos(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.acos(arg) -// } -// -// override fun atan(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.atan(arg) -// } -// -// override fun sinh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.sinh(arg) -// } -// -// override fun cosh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.cosh(arg) -// } -// -// override fun tanh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.tanh(arg) -// } -// -// override fun asinh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.asinh(arg) -// } -// -// override fun acosh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.acosh(arg) -// } -// -// override fun atanh(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.atanh(arg) -// } -// -// override fun power(arg: Buffer, pow: Number): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.power(arg, pow) -// } -// -// override fun exp(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.exp(arg) -// } -// -// override fun ln(arg: Buffer): DoubleBuffer { -// require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } -// return DoubleBufferOperations.ln(arg) -// } - } \ No newline at end of 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 ded8753a3..7ba1a7066 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 @@ -6,10 +6,8 @@ package space.kscience.kmath.operations import space.kscience.kmath.linear.Point -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBufferFactory -import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.structures.* import kotlin.math.* /** @@ -19,10 +17,29 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte Norm, Double> { override val elementAlgebra: DoubleField get() = DoubleField + override val elementBufferFactory: MutableBufferFactory get() = elementAlgebra.bufferFactory - override fun Buffer.map(block: DoubleField.(Double) -> Double): DoubleBuffer = - mapInline { DoubleField.block(it) } + @Suppress("OVERRIDE_BY_INLINE") + @OptIn(UnstableKMathAPI::class) + final override inline fun Buffer.map(block: DoubleField.(Double) -> Double): DoubleBuffer = + DoubleArray(size) { DoubleField.block(getDouble(it)) }.asBuffer() + + + @OptIn(UnstableKMathAPI::class) + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun Buffer.mapIndexed(block: DoubleField.(index: Int, arg: Double) -> Double): DoubleBuffer = + DoubleBuffer(size) { DoubleField.block(it, getDouble(it)) } + + @OptIn(UnstableKMathAPI::class) + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun Buffer.zip( + other: Buffer, + block: DoubleField.(left: Double, right: Double) -> Double, + ): DoubleBuffer { + require(size == other.size) { "Incompatible buffer sizes. left: ${size}, right: ${other.size}" } + return DoubleBuffer(size) { DoubleField.block(getDouble(it), other.getDouble(it)) } + } override fun unaryOperationFunction(operation: String): (arg: Buffer) -> Buffer = super.unaryOperationFunction(operation) @@ -30,7 +47,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte override fun binaryOperationFunction(operation: String): (left: Buffer, right: Buffer) -> Buffer = super.binaryOperationFunction(operation) - override fun Buffer.unaryMinus(): DoubleBuffer = mapInline { -it } + override fun Buffer.unaryMinus(): DoubleBuffer = map { -it } override fun add(left: Buffer, right: Buffer): DoubleBuffer { require(right.size == left.size) { @@ -77,6 +94,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte // } else RealBuffer(DoubleArray(a.size) { a[it] / kValue }) // } + @UnstableKMathAPI override fun multiply(left: Buffer, right: Buffer): DoubleBuffer { require(right.size == left.size) { "The size of the first buffer ${left.size} should be the same as for second one: ${right.size} " @@ -101,55 +119,83 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte } else DoubleBuffer(DoubleArray(left.size) { left[it] / right[it] }) } - override fun sin(arg: Buffer): DoubleBuffer = arg.mapInline(::sin) + override fun sin(arg: Buffer): DoubleBuffer = arg.map { sin(it) } - override fun cos(arg: Buffer): DoubleBuffer = arg.mapInline(::cos) + override fun cos(arg: Buffer): DoubleBuffer = arg.map { cos(it) } - override fun tan(arg: Buffer): DoubleBuffer = arg.mapInline(::tan) + override fun tan(arg: Buffer): DoubleBuffer = arg.map { tan(it) } - override fun asin(arg: Buffer): DoubleBuffer = arg.mapInline(::asin) + override fun asin(arg: Buffer): DoubleBuffer = arg.map { asin(it) } - override fun acos(arg: Buffer): DoubleBuffer = arg.mapInline(::acos) + override fun acos(arg: Buffer): DoubleBuffer = arg.map { acos(it) } - override fun atan(arg: Buffer): DoubleBuffer = arg.mapInline(::atan) + override fun atan(arg: Buffer): DoubleBuffer = arg.map { atan(it) } - override fun sinh(arg: Buffer): DoubleBuffer = arg.mapInline(::sinh) + override fun sinh(arg: Buffer): DoubleBuffer = arg.map { sinh(it) } - override fun cosh(arg: Buffer): DoubleBuffer = arg.mapInline(::cosh) + override fun cosh(arg: Buffer): DoubleBuffer = arg.map { cosh(it) } - override fun tanh(arg: Buffer): DoubleBuffer = arg.mapInline(::tanh) + override fun tanh(arg: Buffer): DoubleBuffer = arg.map { tanh(it) } - override fun asinh(arg: Buffer): DoubleBuffer = arg.mapInline(::asinh) + override fun asinh(arg: Buffer): DoubleBuffer = arg.map { asinh(it) } - override fun acosh(arg: Buffer): DoubleBuffer = arg.mapInline(::acosh) + override fun acosh(arg: Buffer): DoubleBuffer = arg.map { acosh(it) } - override fun atanh(arg: Buffer): DoubleBuffer = arg.mapInline(::atanh) + override fun atanh(arg: Buffer): DoubleBuffer = arg.map { atanh(it) } - override fun exp(arg: Buffer): DoubleBuffer = arg.mapInline(::exp) + override fun exp(arg: Buffer): DoubleBuffer = arg.map { exp(it) } - override fun ln(arg: Buffer): DoubleBuffer = arg.mapInline(::ln) + override fun ln(arg: Buffer): DoubleBuffer = arg.map { ln(it) } override fun norm(arg: Buffer): Double = DoubleL2Norm.norm(arg) - override fun scale(a: Buffer, value: Double): DoubleBuffer = a.mapInline { it * value } + override fun scale(a: Buffer, value: Double): DoubleBuffer = a.map { it * value } override fun power(arg: Buffer, pow: Number): Buffer = if (pow is Int) { - arg.mapInline { it.pow(pow) } + arg.map { it.pow(pow) } } else { - arg.mapInline { it.pow(pow.toDouble()) } + arg.map { it.pow(pow.toDouble()) } } - public companion object : DoubleBufferOps() { - public inline fun Buffer.mapInline(block: (Double) -> Double): DoubleBuffer = - if (this is DoubleBuffer) { - DoubleArray(size) { block(array[it]) }.asBuffer() - } else { - DoubleArray(size) { block(get(it)) }.asBuffer() - } - } + public companion object : DoubleBufferOps() } public object DoubleL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.fold(0.0) { acc: Double, d: Double -> acc + d.pow(2) }) } +public fun DoubleBufferOps.sum(buffer: Buffer): Double = buffer.reduce(Double::plus) + +/** + * Sum of elements using given [conversion] + */ +public inline fun DoubleBufferOps.sumOf(buffer: Buffer, conversion: (T) -> Double): Double = + buffer.fold(0.0) { acc, value -> acc + conversion(value) } + +public fun DoubleBufferOps.average(buffer: Buffer): Double = sum(buffer) / buffer.size + +/** + * Average of elements using given [conversion] + */ +public inline fun DoubleBufferOps.averageOf(buffer: Buffer, conversion: (T) -> Double): Double = + sumOf(buffer, conversion) / buffer.size + +public fun DoubleBufferOps.dispersion(buffer: Buffer): Double { + val av = average(buffer) + return buffer.fold(0.0) { acc, value -> acc + (value - av).pow(2) } / buffer.size +} + +public fun DoubleBufferOps.std(buffer: Buffer): Double = sqrt(dispersion(buffer)) + +public fun DoubleBufferOps.covariance(x: Buffer, y: Buffer): Double { + require(x.size == y.size) { "Expected buffers of the same size, but x.size == ${x.size} and y.size == ${y.size}" } + val xMean = average(x) + val yMean = average(y) + var sum = 0.0 + x.indices.forEach { + sum += (x[it] - xMean) * (y[it] - yMean) + } + return sum / (x.size - 1) +} + + 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 efadfb3cc..f05ddafb8 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 @@ -5,6 +5,21 @@ package space.kscience.kmath.operations +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.structures.Buffer + +/** + * Returns the sum of all elements in the iterable in this [Group]. + * + * @receiver the algebra that provides addition. + * @param data the iterable to sum up. + * @return the sum. + */ +@PerformancePitfall("Potential boxing access to buffer elements") +public fun Group.sum(data: Buffer): T = data.fold(zero) { left, right -> + add(left, right) +} + /** * Returns the sum of all elements in the iterable in this [Group]. * @@ -29,6 +44,18 @@ public fun Group.sum(data: Sequence): T = data.fold(zero) { left, righ add(left, right) } +/** + * Returns an average value of elements in the iterable in this [Group]. + * + * @receiver the algebra that provides addition and division. + * @param data the iterable to find average. + * @return the average value. + * @author Iaroslav Postovalov + */ +@PerformancePitfall("Potential boxing access to buffer elements") +public fun S.average(data: Buffer): T where S : Group, S : ScaleOperations = + sum(data) / data.size + /** * Returns an average value of elements in the iterable in this [Group]. * @@ -95,4 +122,3 @@ public fun Iterable.averageWith(space: S): T where S : Group, S : S */ public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(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 5a8594616..1696d5055 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 @@ -57,6 +57,9 @@ public fun Buffer.toDoubleArray(): DoubleArray = when (this) { else -> DoubleArray(size, ::get) } +/** + * Represent this buffer as [DoubleBuffer]. Does not guarantee that changes in the original buffer are reflected on this buffer. + */ public fun Buffer.toDoubleBuffer(): DoubleBuffer = when (this) { is DoubleBuffer -> this else -> DoubleArray(size, ::get).asBuffer() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt index 0a5d6b964..0a475187f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferExtensions.kt @@ -61,18 +61,18 @@ public fun Buffer.toMutableList(): MutableList = when (this) { */ @UnstableKMathAPI public inline fun Buffer.toTypedArray(): Array = Array(size, ::get) - -/** - * 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 = - Buffer.auto(size) { block(get(it)) } +// +///** +// * 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 = +// 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.mapToBuffer( bufferFactory: BufferFactory, crossinline block: (T) -> R, ): Buffer = bufferFactory(size) { block(get(it)) } @@ -81,23 +81,24 @@ public inline fun Buffer.map( * 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( +public inline fun Buffer.mapIndexedToBuffer( 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)) } +// +///** +// * 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 { + if (size == 0) return initial var accumulator = initial for (index in this.indices) accumulator = operation(accumulator, get(index)) return accumulator @@ -107,18 +108,31 @@ public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R) * Fold given buffer according to indexed [operation] */ public inline fun Buffer.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R { + if (size == 0) return initial var accumulator = initial for (index in this.indices) accumulator = operation(index, accumulator, get(index)) return accumulator } +/** + * Reduce a buffer from left to right according to [operation] + */ +public inline fun Buffer.reduce(operation: (left: T, value: T) -> T): T { + require(size > 0) { "Buffer must have elements" } + var current = get(0) + for (i in 1 until size) { + current = operation(current, get(i)) + } + return current +} + /** * Zip two buffers using given [transform]. */ @UnstableKMathAPI -public inline fun Buffer.zip( +public inline fun Buffer.combineToBuffer( other: Buffer, - bufferFactory: BufferFactory = BufferFactory.auto(), + bufferFactory: BufferFactory, 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/structures/types.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/types.kt new file mode 100644 index 000000000..4ace17538 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/types.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.structures + + +public typealias Float32 = Float +public typealias Float64 = Double + +public typealias Int8 = Byte +public typealias Int16 = Short +public typealias Int32 = Int +public typealias Int64 = Long + +public typealias UInt8 = UByte +public typealias UInt16 = UShort +public typealias UInt32 = UInt +public typealias UInt64 = ULong \ No newline at end of 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 3f06693b0..7bae388a8 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 @@ -81,9 +81,7 @@ public suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCol public suspend inline fun AsyncFlow.collect( concurrency: Int, crossinline action: suspend (value: T) -> Unit, -): Unit = collect(concurrency, object : FlowCollector { - override suspend fun emit(value: T): Unit = action(value) -}) +): Unit = collect(concurrency, FlowCollector { value -> action(value) }) public inline fun Flow.mapParallel( dispatcher: CoroutineDispatcher = Dispatchers.Default, 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 3845bd2a7..fc76ea819 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.operations.map +import space.kscience.kmath.operations.mapToBuffer import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer @@ -33,11 +33,11 @@ public fun GaussIntegratorRuleFactory.build( val normalized: Pair, Buffer> = build(numPoints) val length = range.endInclusive - range.start - val points = normalized.first.map(::DoubleBuffer) { + val points = normalized.first.mapToBuffer(::DoubleBuffer) { range.start + length / 2 + length / 2 * it } - val weights = normalized.second.map(::DoubleBuffer) { + val weights = normalized.second.mapToBuffer(::DoubleBuffer) { it * length / 2 } 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 9a8f475c8..c66674fbb 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 @@ -65,9 +65,9 @@ public class SplineIntegrator>( DoubleBuffer(numPoints) { i -> range.start + i * step } } - val values = nodes.map(bufferFactory) { integrand.function(it) } + val values = nodes.mapToBuffer(bufferFactory) { integrand.function(it) } val polynomials = interpolator.interpolatePolynomials( - nodes.map(bufferFactory) { number(it) }, + nodes.mapToBuffer(bufferFactory) { number(it) }, values ) val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) @@ -93,7 +93,7 @@ public object DoubleSplineIntegrator : UnivariateIntegrator { DoubleBuffer(numPoints) { i -> range.start + i * step } } - val values = nodes.map { integrand.function(it) } + val values = nodes.mapToBuffer(::DoubleBuffer) { integrand.function(it) } val polynomials = interpolator.interpolatePolynomials(nodes, values) val res = polynomials.integrate(DoubleField, range) return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) 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 f22ea9776..b62780ed5 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 @@ -97,7 +97,7 @@ public class UniformHistogramGroupND>( } } hBuilder.apply(builder) - val values: BufferND = BufferND(ndCounter.indices, ndCounter.buffer.map(valueBufferFactory) { it.value }) + val values: BufferND = BufferND(ndCounter.indices, ndCounter.buffer.mapToBuffer(valueBufferFactory) { it.value }) return HistogramND(this, values) } diff --git a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index afd292904..d52420fc6 100644 --- a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -12,6 +12,7 @@ import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.randomNormal import space.kscience.kmath.tensors.core.tensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue 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 62bfe90ba..ef7b7f257 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 @@ -118,35 +118,35 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor = ndBase.get().argmax(ndArray, keepDim, dim).asIntStructure() - override fun StructureND.mean(dim: Int, keepDim: Boolean): Nd4jArrayStructure = - ndArray.mean(keepDim, dim).wrap() + override fun mean(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + structureND.ndArray.mean(keepDim, dim).wrap() - override fun StructureND.exp(): Nd4jArrayStructure = Transforms.exp(ndArray).wrap() - override fun StructureND.ln(): Nd4jArrayStructure = Transforms.log(ndArray).wrap() - override fun StructureND.sqrt(): Nd4jArrayStructure = Transforms.sqrt(ndArray).wrap() - override fun StructureND.cos(): Nd4jArrayStructure = Transforms.cos(ndArray).wrap() - override fun StructureND.acos(): Nd4jArrayStructure = Transforms.acos(ndArray).wrap() - override fun StructureND.cosh(): Nd4jArrayStructure = Transforms.cosh(ndArray).wrap() + override fun exp(arg: StructureND): Nd4jArrayStructure = Transforms.exp(arg.ndArray).wrap() + override fun ln(arg: StructureND): Nd4jArrayStructure = Transforms.log(arg.ndArray).wrap() + override fun sqrt(arg: StructureND): Nd4jArrayStructure = Transforms.sqrt(arg.ndArray).wrap() + override fun cos(arg: StructureND): Nd4jArrayStructure = Transforms.cos(arg.ndArray).wrap() + override fun acos(arg: StructureND): Nd4jArrayStructure = Transforms.acos(arg.ndArray).wrap() + override fun cosh(arg: StructureND): Nd4jArrayStructure = Transforms.cosh(arg.ndArray).wrap() - override fun StructureND.acosh(): Nd4jArrayStructure = - Nd4j.getExecutioner().exec(ACosh(ndArray, ndArray.ulike())).wrap() + override fun acosh(arg: StructureND): Nd4jArrayStructure = + Nd4j.getExecutioner().exec(ACosh(arg.ndArray, arg.ndArray.ulike())).wrap() - override fun StructureND.sin(): Nd4jArrayStructure = Transforms.sin(ndArray).wrap() - override fun StructureND.asin(): Nd4jArrayStructure = Transforms.asin(ndArray).wrap() - override fun StructureND.sinh(): Tensor = Transforms.sinh(ndArray).wrap() + override fun sin(arg: StructureND): Nd4jArrayStructure = Transforms.sin(arg.ndArray).wrap() + override fun asin(arg: StructureND): Nd4jArrayStructure = Transforms.asin(arg.ndArray).wrap() + override fun sinh(arg: StructureND): Tensor = Transforms.sinh(arg.ndArray).wrap() - override fun StructureND.asinh(): Nd4jArrayStructure = - Nd4j.getExecutioner().exec(ASinh(ndArray, ndArray.ulike())).wrap() + override fun asinh(arg: StructureND): Nd4jArrayStructure = + Nd4j.getExecutioner().exec(ASinh(arg.ndArray, arg.ndArray.ulike())).wrap() - override fun StructureND.tan(): Nd4jArrayStructure = Transforms.tan(ndArray).wrap() - 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 tan(arg: StructureND): Nd4jArrayStructure = Transforms.tan(arg.ndArray).wrap() + override fun atan(arg: StructureND): Nd4jArrayStructure = Transforms.atan(arg.ndArray).wrap() + override fun tanh(arg: StructureND): Nd4jArrayStructure = Transforms.tanh(arg.ndArray).wrap() + override fun atanh(arg: StructureND): Nd4jArrayStructure = Transforms.atanh(arg.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 = - ndArray.std(true, keepDim, dim).wrap() + override fun ceil(arg: StructureND): Nd4jArrayStructure = Transforms.ceil(arg.ndArray).wrap() + override fun floor(structureND: StructureND): Nd4jArrayStructure = Transforms.floor(structureND.ndArray).wrap() + override fun std(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + structureND.ndArray.std(true, keepDim, dim).wrap() override fun T.div(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rdiv(this).wrap() override fun StructureND.div(arg: T): Nd4jArrayStructure = ndArray.div(arg).wrap() @@ -160,8 +160,8 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe ndArray.divi(arg.ndArray) } - override fun StructureND.variance(dim: Int, keepDim: Boolean): Nd4jArrayStructure = - Nd4j.getExecutioner().exec(Variance(ndArray, true, true, dim)).wrap() + override fun variance(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + Nd4j.getExecutioner().exec(Variance(structureND.ndArray, true, true, dim)).wrap() private companion object { private val ndBase: ThreadLocal = ThreadLocal.withInitial(::NDBase) @@ -211,7 +211,7 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { override fun StructureND.sum(): Double = ndArray.sumNumber().toDouble() override fun StructureND.min(): Double = ndArray.minNumber().toDouble() override fun StructureND.max(): Double = ndArray.maxNumber().toDouble() - override fun StructureND.mean(): Double = ndArray.meanNumber().toDouble() - override fun StructureND.std(): Double = ndArray.stdNumber().toDouble() - override fun StructureND.variance(): Double = ndArray.varNumber().toDouble() + override fun mean(structureND: StructureND): Double = structureND.ndArray.meanNumber().toDouble() + override fun std(structureND: StructureND): Double = structureND.ndArray.stdNumber().toDouble() + override fun variance(structureND: StructureND): Double = structureND.ndArray.varNumber().toDouble() } diff --git a/kmath-optimization/src/commonMain/tmp/minuit/HessianGradientCalculator.kt b/kmath-optimization/src/commonMain/tmp/minuit/HessianGradientCalculator.kt index 150d192f9..4ef743955 100644 --- a/kmath-optimization/src/commonMain/tmp/minuit/HessianGradientCalculator.kt +++ b/kmath-optimization/src/commonMain/tmp/minuit/HessianGradientCalculator.kt @@ -33,7 +33,7 @@ internal class HessianGradientCalculator(fcn: MnFcn, par: MnUserTransformation, val g2: RealVector = gradient.getGradientDerivative() val gstep: RealVector = gradient.getStep() val fcnmin: Double = par.fval() - // std::cout<<"fval: "< prec.eps()) { return e } - // std::cout<<"MnPosDef init matrix= "<( @Deprecated("Use Long.mean instead") public val long: Mean = Mean(LongRing) { sum, count -> sum / count } - public fun evaluate(buffer: Buffer): Double = Double.mean.evaluateBlocking(buffer) - public fun evaluate(buffer: Buffer): Int = Int.mean.evaluateBlocking(buffer) - public fun evaluate(buffer: Buffer): Long = Long.mean.evaluateBlocking(buffer) + public fun evaluate(buffer: Buffer): Double = DoubleField.mean.evaluateBlocking(buffer) + public fun evaluate(buffer: Buffer): Int = IntRing.mean.evaluateBlocking(buffer) + public fun evaluate(buffer: Buffer): Long = LongRing.mean.evaluateBlocking(buffer) } } //TODO replace with optimized version which respects overflow -public val Double.Companion.mean: Mean get() = Mean(DoubleField) { sum, count -> sum / count } -public val Int.Companion.mean: Mean get() = Mean(IntRing) { sum, count -> sum / count } -public val Long.Companion.mean: Mean get() = Mean(LongRing) { sum, count -> sum / count } +public val DoubleField.mean: Mean get() = Mean(DoubleField) { sum, count -> sum / count } +public val IntRing.mean: Mean get() = Mean(IntRing) { sum, count -> sum / count } +public val LongRing.mean: Mean get() = Mean(LongRing) { sum, count -> sum / count } 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 264d62246..3be7fa314 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 @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.take import kotlinx.coroutines.runBlocking +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.random.chain import space.kscience.kmath.streaming.chunked @@ -27,26 +28,26 @@ internal class StatisticTest { @Test fun singleBlockingMean() { - val first = runBlocking { chunked.first()} - val res = Double.mean(first) - assertEquals(0.5,res, 1e-1) + val first = runBlocking { chunked.first() } + val res = DoubleField.mean(first) + assertEquals(0.5, res, 1e-1) } @Test fun singleSuspendMean() = runBlocking { - val first = runBlocking { chunked.first()} - val res = Double.mean(first) - assertEquals(0.5,res, 1e-1) + val first = runBlocking { chunked.first() } + val res = DoubleField.mean(first) + assertEquals(0.5, res, 1e-1) } @Test fun parallelMean() = runBlocking { - val average = Double.mean + val average = DoubleField.mean .flow(chunked) //create a flow from evaluated results .take(100) // Take 100 data chunks from the source and accumulate them .last() //get 1e5 data samples average - assertEquals(0.5,average, 1e-2) + assertEquals(0.5, average, 1e-2) } } 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 ff11dc8fe..af754f841 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 @@ -13,6 +13,7 @@ import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.sum +import space.kscience.kmath.tensors.core.randomNormal import kotlin.test.assertEquals @OptIn(UnstableKMathAPI::class) 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 587096500..1a324b200 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 @@ -21,7 +21,7 @@ public interface AnalyticTensorAlgebra> : /** * @return the mean of all elements in the input tensor. */ - public fun StructureND.mean(): T + public fun mean(structureND: StructureND): T /** * Returns the mean of each row of the input tensor in the given dimension [dim]. @@ -34,12 +34,12 @@ public interface AnalyticTensorAlgebra> : * @param keepDim whether the output tensor has [dim] retained or not. * @return the mean of each row of the input tensor in the given dimension [dim]. */ - public fun StructureND.mean(dim: Int, keepDim: Boolean): Tensor + public fun mean(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor /** * @return the standard deviation of all elements in the input tensor. */ - public fun StructureND.std(): T + public fun std(structureND: StructureND): T /** * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. @@ -52,12 +52,12 @@ public interface AnalyticTensorAlgebra> : * @param keepDim whether the output tensor has [dim] retained or not. * @return the standard deviation of each row of the input tensor in the given dimension [dim]. */ - public fun StructureND.std(dim: Int, keepDim: Boolean): Tensor + public fun std(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor /** * @return the variance of all elements in the input tensor. */ - public fun StructureND.variance(): T + public fun variance(structureND: StructureND): T /** * Returns the variance of each row of the input tensor in the given dimension [dim]. @@ -70,80 +70,45 @@ public interface AnalyticTensorAlgebra> : * @param keepDim whether the output tensor has [dim] retained or not. * @return the variance of each row of the input tensor in the given dimension [dim]. */ - public fun StructureND.variance(dim: Int, keepDim: Boolean): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.exp.html - public fun StructureND.exp(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.log.html - public fun StructureND.ln(): Tensor + public fun variance(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html - public fun StructureND.sqrt(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos - public fun StructureND.cos(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos - public fun StructureND.acos(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh - public fun StructureND.cosh(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh - public fun StructureND.acosh(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin - public fun StructureND.sin(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin - public fun StructureND.asin(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh - public fun StructureND.sinh(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh - public fun StructureND.asinh(): Tensor + override fun sqrt(arg: StructureND): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan - public fun StructureND.tan(): Tensor + override fun tan(arg: StructureND): Tensor //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan - public fun StructureND.atan(): Tensor + override fun atan(arg: StructureND): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh - public fun StructureND.tanh(): Tensor - - //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh - public fun StructureND.atanh(): Tensor + override fun tanh(arg: StructureND): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil - public fun StructureND.ceil(): Tensor + public fun ceil(arg: StructureND): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor - public fun StructureND.floor(): Tensor + public fun floor(structureND: StructureND): Tensor - override fun sin(arg: StructureND): StructureND = arg.sin() + override fun sin(arg: StructureND): StructureND - override fun cos(arg: StructureND): StructureND = arg.cos() + override fun cos(arg: StructureND): StructureND - override fun asin(arg: StructureND): StructureND = arg.asin() + override fun asin(arg: StructureND): StructureND - override fun acos(arg: StructureND): StructureND = arg.acos() + override fun acos(arg: StructureND): StructureND - override fun atan(arg: StructureND): StructureND = arg.atan() + override fun exp(arg: StructureND): StructureND - override fun exp(arg: StructureND): StructureND = arg.exp() + override fun ln(arg: StructureND): StructureND - override fun ln(arg: StructureND): StructureND = arg.ln() + override fun sinh(arg: StructureND): StructureND - override fun sinh(arg: StructureND): StructureND = arg.sinh() + override fun cosh(arg: StructureND): StructureND - override fun cosh(arg: StructureND): StructureND = arg.cosh() + override fun asinh(arg: StructureND): StructureND - override fun asinh(arg: StructureND): StructureND = arg.asinh() + override fun acosh(arg: StructureND): StructureND - override fun acosh(arg: StructureND): StructureND = arg.acosh() - - override fun atanh(arg: StructureND): StructureND = arg.atanh() + override fun atanh(arg: StructureND): StructureND } \ No newline at end of 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 e15fbb3a6..faff2eb80 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 @@ -47,7 +47,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return the batch of `L` matrices. */ - public fun StructureND.cholesky(): StructureND + public fun cholesky(structureND: StructureND): StructureND /** * QR decomposition. @@ -61,7 +61,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return pair of `Q` and `R` tensors. */ - public fun StructureND.qr(): Pair, StructureND> + public fun qr(structureND: StructureND): Pair, StructureND> /** * LUP decomposition @@ -75,7 +75,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return triple of P, L and U tensors */ - public fun StructureND.lu(): Triple, StructureND, StructureND> + public fun lu(structureND: StructureND): Triple, StructureND, StructureND> /** * Singular Value Decomposition. @@ -91,7 +91,7 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return triple `Triple(U, S, V)`. */ - public fun StructureND.svd(): Triple, StructureND, StructureND> + public fun svd(structureND: StructureND): Triple, StructureND, StructureND> /** * Returns eigenvalues and eigenvectors of a real symmetric matrix `input` or a batch of real symmetric matrices, @@ -101,6 +101,6 @@ public interface LinearOpsTensorAlgebra> : TensorPartialDivision * @receiver the `input`. * @return a pair `eigenvalues to eigenvectors` */ - public fun StructureND.symEig(): Pair, StructureND> + public fun symEig(structureND: StructureND): Pair, StructureND> } 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 12e9549da..4eed7a2a8 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 @@ -10,7 +10,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString -import kotlin.jvm.JvmInline public class OffsetDoubleBuffer( override val origin: DoubleBuffer, @@ -83,9 +82,9 @@ public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { * * [DoubleTensor] always uses row-based strides */ -public class DoubleTensor( +public open class DoubleTensor( shape: ShapeND, - override val source: OffsetDoubleBuffer, + final override val source: OffsetDoubleBuffer, ) : BufferedTensor(shape), MutableStructureNDOfDouble { init { @@ -103,7 +102,7 @@ public class DoubleTensor( source[indices.offset(index)] = value } - override fun getDouble(index: IntArray): Double = get(index) + override fun getDouble(index: IntArray): Double = source[indices.offset(index)] override fun setDouble(index: IntArray, value: Double) { set(index, value) @@ -112,62 +111,8 @@ public class DoubleTensor( override fun toString(): String = toPrettyString() } -@JvmInline -public value class DoubleTensor2D(public val tensor: DoubleTensor) : MutableStructureND by tensor, - MutableStructure2D { - - init { - require(tensor.shape.size == 2) { "Only 2D tensors could be cast to 2D" } - } - - override val rowNum: Int get() = shape[0] - override val colNum: Int get() = shape[1] - - override fun get(i: Int, j: Int): Double = tensor.source[i * colNum + j] - - override fun set(i: Int, j: Int, value: Double) { - tensor.source[i * colNum + j] = value - } - - @OptIn(PerformancePitfall::class) - override val rows: List - get() = List(rowNum) { i -> - tensor.source.view(i * colNum, colNum) - } - - - @OptIn(PerformancePitfall::class) - override val columns: List> - get() = List(colNum) { j -> - val indices = IntArray(rowNum) { i -> j + i * colNum } - tensor.source.permute(indices) - } - - @PerformancePitfall - override fun elements(): Sequence> = tensor.elements() - @OptIn(PerformancePitfall::class) - override fun get(index: IntArray): Double = tensor[index] - override val shape: ShapeND get() = tensor.shape -} - -public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D = DoubleTensor2D(this) - public fun DoubleTensor.asDoubleBuffer(): OffsetDoubleBuffer = if (shape.size == 1) { source } else { error("Only 1D tensors could be cast to 1D") } - -public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: DoubleTensor2D) -> Unit) { - 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 = ShapeND(shape[n - 2], shape[n - 1]) - - val size = matrixShape.linearSize - for (i in 0 until linearSize / matrixOffset) { - val offset = i * matrixOffset - val index = indices.index(offset).sliceArray(0 until (shape.size - 2)) - block(index, DoubleTensor(matrixShape, source.view(offset, size)).asDoubleTensor2D()) - } -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor1D.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor1D.kt new file mode 100644 index 000000000..e74f73800 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor1D.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2018-2022 KMath 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.MutableStructure1D +import space.kscience.kmath.nd.ShapeND +import space.kscience.kmath.structures.MutableBuffer + +public class DoubleTensor1D( + source: OffsetDoubleBuffer, +) : DoubleTensor(ShapeND(source.size), source), MutableStructure1D { + + @PerformancePitfall + override fun get(index: IntArray): Double = super.get(index) + + @PerformancePitfall + override fun set(index: IntArray, value: Double) { + super.set(index, value) + } + + override val size: Int get() = source.size + + override fun get(index: Int): Double = source[index] + + override fun set(index: Int, value: Double) { + source[index] = value + } + + override fun copy(): MutableBuffer = source.copy() + + @PerformancePitfall + override fun elements(): Sequence> = super.elements() +} + +/** + * A zero-copy cast to 1D structure. Changes in resulting structure are reflected on original tensor. + */ +public fun DoubleTensor.asDoubleTensor1D(): DoubleTensor1D { + require(shape.size == 1) { "Only 1D tensors could be cast to 1D" } + return DoubleTensor1D(source) +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor2D.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor2D.kt new file mode 100644 index 000000000..7c84b91e1 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor2D.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2018-2022 KMath 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.MutableStructure2D +import space.kscience.kmath.nd.ShapeND +import space.kscience.kmath.nd.linearSize +import space.kscience.kmath.structures.PermutedMutableBuffer +import space.kscience.kmath.structures.permute + +public class DoubleTensor2D( + override val rowNum: Int, + override val colNum: Int, + source: OffsetDoubleBuffer, +) : DoubleTensor(ShapeND(rowNum, colNum), source), MutableStructure2D { + + override fun get(i: Int, j: Int): Double = source[i * colNum + j] + + @OptIn(PerformancePitfall::class) + override fun get(index: IntArray): Double = getDouble(index) + + override fun set(i: Int, j: Int, value: Double) { + source[i * colNum + j] = value + } + + @OptIn(PerformancePitfall::class) + override val rows: List + get() = List(rowNum) { i -> + source.view(i * colNum, colNum) + } + + + @OptIn(PerformancePitfall::class) + override val columns: List> + get() = List(colNum) { j -> + val indices = IntArray(rowNum) { i -> j + i * colNum } + source.permute(indices) + } + + override val shape: ShapeND get() = super.shape + + @PerformancePitfall + override fun elements(): Sequence> = super.elements() +} + +/** + * A zero-copy cast to 2D structure. Changes in resulting structure are reflected on original tensor. + */ +public fun DoubleTensor.asDoubleTensor2D(): DoubleTensor2D { + require(shape.size == 2) { "Only 2D tensors could be cast to 2D" } + return DoubleTensor2D(shape[0], shape[1], source) +} + + +public inline fun DoubleTensor.forEachMatrix(block: (index: IntArray, matrix: DoubleTensor2D) -> Unit) { + 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 = ShapeND(shape[n - 2], shape[n - 1]) + + val size = matrixShape.linearSize + for (i in 0 until linearSize / matrixOffset) { + val offset = i * matrixOffset + val index = indices.index(offset).sliceArray(0 until (shape.size - 2)) + block(index, DoubleTensor(matrixShape, source.view(offset, size)).asDoubleTensor2D()) + } +} 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 ce1778013..997c0a316 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 @@ -11,12 +11,12 @@ 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.DoubleBufferOps import space.kscience.kmath.operations.DoubleField 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 -import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.core.internal.* import kotlin.math.* @@ -25,7 +25,6 @@ import kotlin.math.* */ @OptIn(PerformancePitfall::class) public open class DoubleTensorAlgebra : - TensorPartialDivisionAlgebra, AnalyticTensorAlgebra, LinearOpsTensorAlgebra { @@ -33,6 +32,8 @@ public open class DoubleTensorAlgebra : override val elementAlgebra: DoubleField get() = DoubleField + public val bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps + /** * Applies the [transform] function to each element of the tensor and returns the resulting modified tensor. @@ -98,6 +99,16 @@ public open class DoubleTensorAlgebra : override fun StructureND.value(): Double = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") + public fun fromBuffer(shape: ShapeND, buffer: Buffer): DoubleTensor { + checkNotEmptyShape(shape) + check(buffer.size > 0) { "Illegal empty buffer provided" } + check(buffer.size == shape.linearSize) { + "Inconsistent shape $shape for buffer of size ${buffer.size} provided" + } + return DoubleTensor(shape, buffer.toDoubleBuffer()) + } + + /** * Constructs a tensor with the specified shape and data. * @@ -105,12 +116,7 @@ public open class DoubleTensorAlgebra : * @param array one-dimensional data array. * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: ShapeND, array: DoubleArray): DoubleTensor { - checkNotEmptyShape(shape) - checkEmptyDoubleBuffer(array) - checkBufferShapeConsistency(shape, array) - return DoubleTensor(shape, array.asBuffer()) - } + public fun fromArray(shape: ShapeND, array: DoubleArray): DoubleTensor = fromBuffer(shape, array.asBuffer()) /** * Constructs a tensor with the specified shape and initializer. @@ -271,7 +277,7 @@ public open class DoubleTensorAlgebra : override fun StructureND.transposed(i: Int, j: Int): Tensor { val actualI = if (i >= 0) i else shape.size + i - val actualJ = if(j>=0) j else shape.size + j + val actualJ = if (j >= 0) j else shape.size + j return asDoubleTensor().permute( shape.transposed(actualI, actualJ) ) { originIndex -> @@ -498,48 +504,6 @@ public open class DoubleTensorAlgebra : return true } - /** - * Returns a tensor of random numbers drawn from normal distributions with `0.0` mean and `1.0` standard deviation. - * - * @param shape the desired shape for the output tensor. - * @param seed the random seed of the pseudo-random number generator. - * @return tensor of a given shape filled with numbers from the normal distribution - * with `0.0` mean and `1.0` standard deviation. - */ - public fun randomNormal(shape: ShapeND, seed: Long = 0): DoubleTensor = - DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) - - /** - * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions - * with `0.0` mean and `1.0` standard deviation. - * - * @receiver the `input`. - * @param seed the random seed of the pseudo-random number generator. - * @return a tensor with the same shape as `input` filled with numbers from the normal distribution - * with `0.0` mean and `1.0` standard deviation. - */ - public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = - DoubleTensor(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) - - /** - * 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>): DoubleTensor { - 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 = ShapeND(tensors.size) + shape -// 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) - } - /** * Builds tensor from rows of the input tensor. * @@ -631,102 +595,75 @@ public open class DoubleTensorAlgebra : } - override fun StructureND.mean(): Double = sum() / indices.linearSize + override fun mean(structureND: StructureND): Double = structureND.sum() / structureND.indices.linearSize - 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 mean(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + structureND.foldDimToDouble(dim, keepDim) { arr -> + check(dim < structureND.dimension) { "Dimension $dim out of range ${structureND.dimension}" } + arr.sum() / structureND.shape[dim] } - 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 std(structureND: StructureND): Double = structureND.reduceElements { arr -> + val mean = arr.array.sum() / structureND.indices.linearSize + sqrt(arr.array.sumOf { (it - mean) * (it - mean) } / (structureND.indices.linearSize - 1)) } - 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)) - } + override fun std(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + structureND.foldDimToDouble( + dim, + keepDim + ) { arr -> + check(dim < structureND.dimension) { "Dimension $dim out of range ${structureND.dimension}" } + val mean = arr.sum() / structureND.shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (structureND.shape[dim] - 1)) + } - override fun StructureND.variance(): Double = reduceElements { arr -> - val linearSize = indices.linearSize + override fun variance(structureND: StructureND): Double = structureND.reduceElements { arr -> + val linearSize = structureND.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) - } - - private fun cov(x: StructureND, y: StructureND): Double { - val n = x.shape[0] - return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) - } - - /** - * Returns the covariance matrix `M` of given vectors. - * - * `M[i, j]` contains covariance of `i`-th and `j`-th given vectors - * - * @param tensors the [List] of 1-dimensional tensors with same shape - * @return `M`. - */ - public fun cov(tensors: List>): DoubleTensor { - check(tensors.isNotEmpty()) { "List must have at least 1 element" } - val n = tensors.size - val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals ShapeND(m) }) { "Tensors must have same shapes" } - val resTensor = DoubleTensor( - ShapeND(n, n), - DoubleBuffer(n * n) { 0.0 } - ) - for (i in 0 until n) { - for (j in 0 until n) { - resTensor[intArrayOf(i, j)] = cov(tensors[i], tensors[j]) - } + override fun variance(structureND: StructureND, dim: Int, keepDim: Boolean): Tensor = + structureND.foldDimToDouble( + dim, + keepDim + ) { arr -> + check(dim < structureND.dimension) { "Dimension $dim out of range ${structureND.dimension}" } + val mean = arr.sum() / structureND.shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (structureND.shape[dim] - 1) } - return resTensor - } - override fun StructureND.exp(): DoubleTensor = map { exp(it) } - override fun StructureND.ln(): DoubleTensor = map { ln(it) } + override fun exp(arg: StructureND): DoubleTensor = arg.map { this.exp(it) } - override fun StructureND.sqrt(): DoubleTensor = map { sqrt(it) } + override fun ln(arg: StructureND): DoubleTensor = arg.map { this.ln(it) } - override fun StructureND.cos(): DoubleTensor = map { cos(it) } + override fun sqrt(arg: StructureND): DoubleTensor = arg.map { this.sqrt(it) } - override fun StructureND.acos(): DoubleTensor = map { acos(it) } + override fun cos(arg: StructureND): DoubleTensor = arg.map { this.cos(it) } - override fun StructureND.cosh(): DoubleTensor = map { cosh(it) } + override fun acos(arg: StructureND): DoubleTensor = arg.map { this.acos(it) } - override fun StructureND.acosh(): DoubleTensor = map { acosh(it) } + override fun cosh(arg: StructureND): DoubleTensor = arg.map { this.cosh(it) } - override fun StructureND.sin(): DoubleTensor = map { sin(it) } + override fun acosh(arg: StructureND): DoubleTensor = arg.map { this.acosh(it) } - override fun StructureND.asin(): DoubleTensor = map { asin(it) } + override fun sin(arg: StructureND): DoubleTensor = arg.map { this.sin(it) } - override fun StructureND.sinh(): DoubleTensor = map { sinh(it) } + override fun asin(arg: StructureND): DoubleTensor = arg.map { this.asin(it) } - override fun StructureND.asinh(): DoubleTensor = map { asinh(it) } + override fun sinh(arg: StructureND): DoubleTensor = arg.map { this.sinh(it) } - override fun StructureND.tan(): DoubleTensor = map { tan(it) } + override fun asinh(arg: StructureND): DoubleTensor = arg.map { this.asinh(it) } - override fun StructureND.atan(): DoubleTensor = map { atan(it) } + override fun tan(arg: StructureND): DoubleTensor = arg.map { this.tan(it) } - override fun StructureND.tanh(): DoubleTensor = map { tanh(it) } + override fun atan(arg: StructureND): DoubleTensor = arg.map { this.atan(it) } - override fun StructureND.atanh(): DoubleTensor = map { atanh(it) } + override fun tanh(arg: StructureND): DoubleTensor = arg.map { this.tanh(it) } + + override fun atanh(arg: StructureND): DoubleTensor = arg.map { this.atanh(it) } override fun power(arg: StructureND, pow: Number): StructureND = if (pow is Int) { arg.map { it.pow(pow) } @@ -734,115 +671,26 @@ public open class DoubleTensorAlgebra : arg.map { it.pow(pow.toDouble()) } } - override fun StructureND.ceil(): DoubleTensor = map { ceil(it) } + override fun ceil(arg: StructureND): DoubleTensor = arg.map { ceil(it) } - override fun StructureND.floor(): DoubleTensor = map { floor(it) } + override fun floor(structureND: StructureND): DoubleTensor = structureND.map { floor(it) } - override fun StructureND.inv(): DoubleTensor = invLU(1e-9) + override fun StructureND.inv(): DoubleTensor = invLU(this, 1e-9) - override fun StructureND.det(): DoubleTensor = detLU(1e-9) + override fun StructureND.det(): DoubleTensor = detLU(this, 1e-9) - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun StructureND.luFactor(epsilon: Double): Pair = - computeLU(this, epsilon) - ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + override fun lu(structureND: StructureND): Triple = + lu(structureND, 1e-9) - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. - * - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun StructureND.luFactor(): Pair = luFactor(1e-9) + override fun cholesky(structureND: StructureND): DoubleTensor = cholesky(structureND, 1e-6) - /** - * Unpacks the data and pivots from a LU factorization of a tensor. - * Given a tensor [luTensor], return tensors `Triple(P, L, U)` satisfying `P dot luTensor = L dot U`, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param luTensor the packed LU factorization data - * @param pivotsTensor the packed LU factorization pivots - * @return triple of `P`, `L` and `U` tensors - */ - public fun luPivot( - luTensor: StructureND, - pivotsTensor: Tensor, - ): Triple { - checkSquareMatrix(luTensor.shape) - check( - luTensor.shape.first(luTensor.shape.size - 2) contentEquals pivotsTensor.shape.first(pivotsTensor.shape.size - 1) || - luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Inappropriate shapes of input tensors" } - - val n = luTensor.shape.last() - val pTensor = zeroesLike(luTensor) - pTensor - .matrixSequence() - .zip(pivotsTensor.asIntTensor().vectorSequence()) - .forEach { (p, pivot) -> pivInit(p.asDoubleTensor2D(), pivot.as1D(), n) } - - val lTensor = zeroesLike(luTensor) - val uTensor = zeroesLike(luTensor) - - lTensor.matrixSequence() - .zip(uTensor.matrixSequence()) - .zip(luTensor.asDoubleTensor().matrixSequence()) - .forEach { (pairLU, lu) -> - val (l, u) = pairLU - luPivotHelper(l.asDoubleTensor2D(), u.asDoubleTensor2D(), lu.asDoubleTensor2D(), n) - } - - return Triple(pTensor, lTensor, uTensor) - } - - /** - * QR decomposition. - * - * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `Q to R` of tensors. - * Given a tensor `input`, return tensors `Q to R` satisfying `input == Q dot R`, - * with `Q` being an orthogonal matrix or batch of orthogonal matrices - * and `R` being an upper triangular matrix or batch of upper triangular matrices. - * - * @receiver the `input`. - * @param epsilon the permissible error when comparing tensors for equality. - * Used when checking the positive definiteness of the input matrix or matrices. - * @return a pair of `Q` and `R` tensors. - */ - public fun StructureND.cholesky(epsilon: Double): DoubleTensor { - checkSquareMatrix(shape) - checkPositiveDefinite(asDoubleTensor(), epsilon) - - val n = shape.last() - val lTensor = zeroesLike(this) - - for ((a, l) in asDoubleTensor().matrixSequence().zip(lTensor.matrixSequence())) - for (i in 0 until n) choleskyHelper(a.asDoubleTensor2D(), l.asDoubleTensor2D(), n) - - return lTensor - } - - override fun StructureND.cholesky(): DoubleTensor = cholesky(1e-6) - - override fun StructureND.qr(): Pair { - checkSquareMatrix(shape) - val qTensor = zeroesLike(this) - val rTensor = zeroesLike(this) + override fun qr(structureND: StructureND): Pair { + checkSquareMatrix(structureND.shape) + val qTensor = zeroesLike(structureND) + val rTensor = zeroesLike(structureND) //TODO replace with cycle - asDoubleTensor().matrixSequence() + structureND.asDoubleTensor().matrixSequence() .zip( (qTensor.matrixSequence() .zip(rTensor.matrixSequence())) @@ -854,200 +702,14 @@ public open class DoubleTensorAlgebra : return qTensor to rTensor } - override fun StructureND.svd(): Triple, StructureND, StructureND> = - svd(epsilon = 1e-10) + override fun svd( + structureND: StructureND, + ): Triple, StructureND, StructureND> = + svd(structureND = structureND, epsilon = 1e-10) + override fun symEig(structureND: StructureND): Pair = + symEigJacobi(structureND = structureND, maxIteration = 50, epsilon = 1e-15) - /** - * Singular Value Decomposition. - * - * Computes the singular value decomposition of either a matrix or batch of matrices `input`. - * The singular value decomposition is represented as a triple `Triple(U, S, V)`, - * such that `input == U dot diagonalEmbedding(S) dot V.transpose()`. - * If `input` is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as `input. - * - * @receiver the `input`. - * @param epsilon permissible error when calculating the dot product of vectors - * i.e., the precision with which the cosine approaches 1 in an iterative algorithm. - * @return a triple `Triple(U, S, V)`. - */ - public fun StructureND.svd(epsilon: Double): Triple, StructureND, StructureND> { - val size = dimension - val commonShape = shape.slice(0 until size - 2) - val (n, m) = shape.slice(size - 2 until size) - val uTensor = zeros(commonShape + ShapeND(min(n, m), n)) - val sTensor = zeros(commonShape + ShapeND(min(n, m))) - val vTensor = zeros(commonShape + ShapeND(min(n, m), m)) - - val matrices = asDoubleTensor().matrices - val uTensors = uTensor.matrices - val sTensorVectors = sTensor.vectors - val vTensors = vTensor.matrices - - for (index in matrices.indices) { - val matrix = matrices[index] - val usv = Triple( - uTensors[index], - sTensorVectors[index], - vTensors[index] - ) - val matrixSize = matrix.shape.linearSize - val curMatrix = DoubleTensor( - matrix.shape, - matrix.source.view(0, matrixSize) - ) - svdHelper(curMatrix, usv, m, n, epsilon) - } - - return Triple(uTensor.transposed(), sTensor, vTensor.transposed()) - } - - 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, - * represented by a pair `eigenvalues to eigenvectors`. - * - * @param epsilon the permissible error when comparing tensors for equality - * and when the cosine approaches 1 in the SVD algorithm. - * @return a pair `eigenvalues to eigenvectors`. - */ - public fun StructureND.symEigSvd(epsilon: Double): Pair> { - //TODO optimize conversion - checkSymmetric(asDoubleTensor(), epsilon) - - fun MutableStructure2D.cleanSym(n: Int) { - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - this[i, j] = sign(this[i, j]) - } else { - this[i, j] = 0.0 - } - } - } - } - - val (u, s, v) = svd(epsilon) - val shp = s.shape + intArrayOf(1) - val utv = u.transposed() matmul v - val n = s.shape.last() - for (matrix in utv.matrixSequence()) { - matrix.asDoubleTensor2D().cleanSym(n) - } - - val eig = (utv dot s.asDoubleTensor().view(shp)).view(s.shape) - return eig to v - } - - public fun StructureND.symEigJacobi(maxIteration: Int, epsilon: Double): Pair { - //TODO optimize conversion - checkSymmetric(asDoubleTensor(), epsilon) - - val size = this.dimension - val eigenvectors = zeros(shape) - val eigenvalues = zeros(shape.slice(0 until size - 1)) - - var eigenvalueStart = 0 - var eigenvectorStart = 0 - for (matrix in asDoubleTensor().matrixSequence()) { - val matrix2D = matrix.asDoubleTensor2D() - val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) - - for (i in 0 until matrix2D.rowNum) { - for (j in 0 until matrix2D.colNum) { - eigenvectors.source[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] - } - } - - for (i in 0 until matrix2D.rowNum) { - eigenvalues.source[eigenvalueStart + i] = d[i] - } - - eigenvalueStart += this.shape.last() - eigenvectorStart += this.shape.last() * this.shape.last() - } - - return eigenvalues to eigenvectors - } - - /** - * Computes the determinant of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * - * @param epsilon the error in the LU algorithm—permissible error when comparing the determinant of a matrix - * with zero. - * @return the determinant. - */ - public fun StructureND.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(shape) - //TODO check for unnecessary copies - val luTensor = copyToTensor() - val pivotsTensor = setUpPivots() - - val n = shape.size - - val detTensorShape = ShapeND(IntArray(n - 1) { i -> shape[i] }.apply { - set(n - 2, 1) - }) - - val resBuffer = DoubleBuffer(detTensorShape.linearSize) { 0.0 } - - val detTensor = DoubleTensor( - detTensorShape, - resBuffer - ) - - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = if (luHelper(lu.asDoubleTensor2D(), pivots.as1D(), epsilon)) - 0.0 else luMatrixDet(lu.asDoubleTensor2D(), pivots.as1D()) - } - - return detTensor - } - - /** - * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * Given a square matrix `a`, return the matrix `aInv` satisfying - * `a dot aInv == aInv dot a == eye(a.shape[0])`. - * - * @param epsilon error in the LU algorithm—permissible error when comparing the determinant of a matrix with zero - * @return the multiplicative inverse of a matrix. - */ - public fun StructureND.invLU(epsilon: Double = 1e-9): DoubleTensor { - val (luTensor, pivotsTensor) = luFactor(epsilon) - 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 - luMatrixInv(lu.asDoubleTensor2D(), pivots.as1D(), invMatrix.asDoubleTensor2D()) - } - - return invTensor - } - - /** - * LUP decomposition. - * - * Computes the LUP decomposition of a matrix or a batch of matrices. - * Given a tensor `input`, return tensors `Triple(P, L, U)` satisfying `P dot input == L dot U`, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero. - * @return triple of `P`, `L` and `U` tensors. - */ - public fun StructureND.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = luFactor(epsilon) - return luPivot(lu, pivots) - } - - override fun StructureND.lu(): Triple = lu(1e-9) } public val Double.Companion.tensorAlgebra: DoubleTensorAlgebra get() = DoubleTensorAlgebra diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index dcdf49e1e..f384ed462 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -13,6 +13,7 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.asDoubleTensor +import space.kscience.kmath.tensors.core.detLU internal fun checkNotEmptyShape(shape: ShapeND) = @@ -26,7 +27,7 @@ internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmp internal fun checkBufferShapeConsistency(shape: ShapeND, buffer: DoubleArray) = check(buffer.size == shape.linearSize) { - "Inconsistent shape ${shape} for buffer of size ${buffer.size} provided" + "Inconsistent shape $shape for buffer of size ${buffer.size} provided" } @PublishedApi @@ -62,7 +63,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asDoubleTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asDoubleTensor().detLU().value()}" + check(detLU(mat.asDoubleTensor()).value() > 0.0) { + "Tensor contains matrices which are not positive definite ${detLU(mat.asDoubleTensor()).value()}" } } \ 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 44459ad14..cf3697e76 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 @@ -227,7 +227,7 @@ internal fun DoubleTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleTensorAlgebra { sqrt((v dot v)).value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } @@ -250,7 +250,7 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + val norm = DoubleTensorAlgebra { sqrt((v dot v)).value() } v = v.times(1.0 / norm) if (abs(v.dot(lastV).value()) > 1 - epsilon) { return v @@ -283,12 +283,12 @@ internal fun DoubleTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } + norm = DoubleTensorAlgebra { sqrt((u dot u)).value() } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transposed(0, 1).dot(u) - norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + norm = DoubleTensorAlgebra { sqrt((v dot v)).value() } v = v.times(1.0 / norm) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorOps.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorOps.kt new file mode 100644 index 000000000..e5dc55f68 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorOps.kt @@ -0,0 +1,370 @@ +/* + * Copyright 2018-2022 KMath 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.* +import space.kscience.kmath.operations.covariance +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.internal.* +import kotlin.math.min +import kotlin.math.sign + + +/** + * Returns a tensor of random numbers drawn from normal distributions with `0.0` mean and `1.0` standard deviation. + * + * @param shape the desired shape for the output tensor. + * @param seed the random seed of the pseudo-random number generator. + * @return tensor of a given shape filled with numbers from the normal distribution + * with `0.0` mean and `1.0` standard deviation. + */ +public fun DoubleTensorAlgebra.randomNormal(shape: ShapeND, seed: Long = 0): DoubleTensor = + fromBuffer(shape, DoubleBuffer.randomNormals(shape.linearSize, seed)) + +/** + * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions + * with `0.0` mean and `1.0` standard deviation. + * + * @receiver the `input`. + * @param seed the random seed of the pseudo-random number generator. + * @return a tensor with the same shape as `input` filled with numbers from the normal distribution + * with `0.0` mean and `1.0` standard deviation. + */ +public fun DoubleTensorAlgebra.randomNormalLike(structure: WithShape, seed: Long = 0): DoubleTensor = + DoubleTensor(structure.shape, DoubleBuffer.randomNormals(structure.shape.linearSize, seed)) + +/** + * 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>): DoubleTensor { + 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 = ShapeND(tensors.size) + shape +// 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) +} + +/** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero default is 1e-9 + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ +public fun DoubleTensorAlgebra.luFactor( + structureND: StructureND, + epsilon: Double = 1e-9, +): Pair = + computeLU(structureND, epsilon) + ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + + +/** + * Unpacks the data and pivots from a LU factorization of a tensor. + * Given a tensor [luTensor], return tensors `Triple(P, L, U)` satisfying `P dot luTensor = L dot U`, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param luTensor the packed LU factorization data + * @param pivotsTensor the packed LU factorization pivots + * @return triple of `P`, `L` and `U` tensors + */ +public fun DoubleTensorAlgebra.luPivot( + luTensor: StructureND, + pivotsTensor: Tensor, +): Triple { + checkSquareMatrix(luTensor.shape) + check( + luTensor.shape.first(luTensor.shape.size - 2) contentEquals pivotsTensor.shape.first(pivotsTensor.shape.size - 1) || + luTensor.shape.last() == pivotsTensor.shape.last() - 1 + ) { "Inappropriate shapes of input tensors" } + + val n = luTensor.shape.last() + val pTensor = zeroesLike(luTensor) + pTensor + .matrixSequence() + .zip(pivotsTensor.asIntTensor().vectorSequence()) + .forEach { (p, pivot) -> pivInit(p.asDoubleTensor2D(), pivot.as1D(), n) } + + val lTensor = zeroesLike(luTensor) + val uTensor = zeroesLike(luTensor) + + lTensor.matrixSequence() + .zip(uTensor.matrixSequence()) + .zip(luTensor.asDoubleTensor().matrixSequence()) + .forEach { (pairLU, lu) -> + val (l, u) = pairLU + luPivotHelper(l.asDoubleTensor2D(), u.asDoubleTensor2D(), lu.asDoubleTensor2D(), n) + } + + return Triple(pTensor, lTensor, uTensor) +} + + +/** + * LUP decomposition. + * + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors `Triple(P, L, U)` satisfying `P dot input == L dot U`, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero. + * @return triple of `P`, `L` and `U` tensors. + */ +public fun DoubleTensorAlgebra.lu( + structureND: StructureND, + epsilon: Double = 1e-9, +): Triple { + val (lu, pivots) = luFactor(structureND, epsilon) + return luPivot(lu, pivots) +} + + +/** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `Q to R` of tensors. + * Given a tensor `input`, return tensors `Q to R` satisfying `input == Q dot R`, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * + * @receiver the `input`. + * @param epsilon the permissible error when comparing tensors for equality. The default is 1e-6 + * Used when checking the positive definiteness of the input matrix or matrices. + * @return a pair of `Q` and `R` tensors. + */ +public fun DoubleTensorAlgebra.cholesky(structureND: StructureND, epsilon: Double = 1e-6): DoubleTensor { + checkSquareMatrix(structureND.shape) + checkPositiveDefinite(structureND.asDoubleTensor(), epsilon) + + val n = structureND.shape.last() + val lTensor = zeroesLike(structureND) + + for ((a, l) in structureND.asDoubleTensor().matrixSequence().zip(lTensor.matrixSequence())) + for (i in 0 until n) choleskyHelper(a.asDoubleTensor2D(), l.asDoubleTensor2D(), n) + + return lTensor +} + + +/** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a triple `Triple(U, S, V)`, + * such that `input == U dot diagonalEmbedding(S) dot V.transpose()`. + * If `input` is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as `input. + * + * @receiver the `input`. + * @param epsilon permissible error when calculating the dot product of vectors + * i.e., the precision with which the cosine approaches 1 in an iterative algorithm. + * @return a triple `Triple(U, S, V)`. + */ +public fun DoubleTensorAlgebra.svd( + structureND: StructureND, + epsilon: Double, +): Triple, StructureND, StructureND> { + val size = structureND.dimension + val commonShape = structureND.shape.slice(0 until size - 2) + val (n, m) = structureND.shape.slice(size - 2 until size) + val uTensor = zeros(commonShape + ShapeND(min(n, m), n)) + val sTensor = zeros(commonShape + ShapeND(min(n, m))) + val vTensor = zeros(commonShape + ShapeND(min(n, m), m)) + + val matrices = structureND.asDoubleTensor().matrices + val uTensors = uTensor.matrices + val sTensorVectors = sTensor.vectors + val vTensors = vTensor.matrices + + for (index in matrices.indices) { + val matrix = matrices[index] + val usv = Triple( + uTensors[index], + sTensorVectors[index], + vTensors[index] + ) + val matrixSize = matrix.shape.linearSize + val curMatrix = DoubleTensor( + matrix.shape, + matrix.source.view(0, matrixSize) + ) + svdHelper(curMatrix, usv, m, n, epsilon) + } + + return Triple(uTensor.transposed(), sTensor, vTensor.transposed()) +} + +/** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a pair `eigenvalues to eigenvectors`. + * + * @param epsilon the permissible error when comparing tensors for equality + * and when the cosine approaches 1 in the SVD algorithm. + * @return a pair `eigenvalues to eigenvectors`. + */ +public fun DoubleTensorAlgebra.symEigSvd( + structureND: StructureND, + epsilon: Double, +): Pair> { + //TODO optimize conversion + checkSymmetric(structureND.asDoubleTensor(), epsilon) + + fun MutableStructure2D.cleanSym(n: Int) { + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + this[i, j] = sign(this[i, j]) + } else { + this[i, j] = 0.0 + } + } + } + } + + val (u, s, v) = svd(structureND, epsilon) + val shp = s.shape + intArrayOf(1) + val utv = u.transposed() matmul v + val n = s.shape.last() + for (matrix in utv.matrixSequence()) { + matrix.asDoubleTensor2D().cleanSym(n) + } + + val eig = (utv dot s.asDoubleTensor().view(shp)).view(s.shape) + return eig to v +} + +public fun DoubleTensorAlgebra.symEigJacobi( + structureND: StructureND, + maxIteration: Int, + epsilon: Double, +): Pair { + //TODO optimize conversion + checkSymmetric(structureND.asDoubleTensor(), epsilon) + + val size = structureND.dimension + val eigenvectors = zeros(structureND.shape) + val eigenvalues = zeros(structureND.shape.slice(0 until size - 1)) + + var eigenvalueStart = 0 + var eigenvectorStart = 0 + for (matrix in structureND.asDoubleTensor().matrixSequence()) { + val matrix2D = matrix.asDoubleTensor2D() + val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) + + for (i in 0 until matrix2D.rowNum) { + for (j in 0 until matrix2D.colNum) { + eigenvectors.source[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] + } + } + + for (i in 0 until matrix2D.rowNum) { + eigenvalues.source[eigenvalueStart + i] = d[i] + } + + eigenvalueStart += structureND.shape.last() + eigenvectorStart += structureND.shape.last() * structureND.shape.last() + } + + return eigenvalues to eigenvectors +} + +/** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * + * @param epsilon the error in the LU algorithm—permissible error when comparing the determinant of a matrix + * with zero. + * @return the determinant. + */ +public fun DoubleTensorAlgebra.detLU(structureND: StructureND, epsilon: Double = 1e-9): DoubleTensor { + checkSquareMatrix(structureND.shape) + //TODO check for unnecessary copies + val luTensor = structureND.copyToTensor() + val pivotsTensor = structureND.setUpPivots() + + val n = structureND.shape.size + + val detTensorShape = ShapeND(IntArray(n - 1) { i -> structureND.shape[i] }.apply { + set(n - 2, 1) + }) + + val resBuffer = DoubleBuffer(detTensorShape.linearSize) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> + resBuffer[index] = if (luHelper(lu.asDoubleTensor2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.asDoubleTensor2D(), pivots.as1D()) + } + + return detTensor +} + +/** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * `a dot aInv == aInv dot a == eye(a.shape[0])`. + * + * @param epsilon error in the LU algorithm—permissible error when comparing the determinant of a matrix with zero + * @return the multiplicative inverse of a matrix. + */ +public fun DoubleTensorAlgebra.invLU(structureND: StructureND, epsilon: Double = 1e-9): DoubleTensor { + val (luTensor, pivotsTensor) = luFactor(structureND, epsilon) + 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 + luMatrixInv(lu.asDoubleTensor2D(), pivots.as1D(), invMatrix.asDoubleTensor2D()) + } + + return invTensor +} + +/** + * Returns the covariance matrix `M` of given vectors. + * + * `M[i, j]` contains covariance of `i`-th and `j`-th given vectors + * + * @param vectors the [List] of 1-dimensional tensors with same shape + * @return `M`. + */ +public fun DoubleTensorAlgebra.covariance(vectors: List>): DoubleTensor { + check(vectors.isNotEmpty()) { "List must have at least 1 element" } + val n = vectors.size + val m = vectors[0].size + check(vectors.all { it.size == m }) { "Vectors must have same shapes" } + val resTensor = DoubleTensor( + ShapeND(n, n), + DoubleBuffer(n * n) { 0.0 } + ) + for (i in 0 until n) { + for (j in 0 until n) { + resTensor[intArrayOf(i, j)] = bufferAlgebra.covariance(vectors[i], vectors[j]) + } + } + return resTensor +} \ No newline at end of file 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 2ef2d87d6..e4c2c40ea 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 @@ -34,73 +34,73 @@ internal class TestDoubleAnalyticTensorAlgebra { @Test fun testExp() = DoubleTensorAlgebra { - assertTrue { tensor.exp() eq expectedTensor(::exp) } + assertTrue { exp(tensor) eq expectedTensor(::exp) } } @Test fun testLog() = DoubleTensorAlgebra { - assertTrue { tensor.ln() eq expectedTensor(::ln) } + assertTrue { ln(tensor) eq expectedTensor(::ln) } } @Test fun testSqrt() = DoubleTensorAlgebra { - assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) } + assertTrue { sqrt(tensor) eq expectedTensor(::sqrt) } } @Test fun testCos() = DoubleTensorAlgebra { - assertTrue { tensor.cos() eq expectedTensor(::cos) } + assertTrue { cos(tensor) eq expectedTensor(::cos) } } @Test fun testCosh() = DoubleTensorAlgebra { - assertTrue { tensor.cosh() eq expectedTensor(::cosh) } + assertTrue { cosh(tensor) eq expectedTensor(::cosh) } } @Test fun testAcosh() = DoubleTensorAlgebra { - assertTrue { tensor.acosh() eq expectedTensor(::acosh) } + assertTrue { acosh(tensor) eq expectedTensor(::acosh) } } @Test fun testSin() = DoubleTensorAlgebra { - assertTrue { tensor.sin() eq expectedTensor(::sin) } + assertTrue { sin(tensor) eq expectedTensor(::sin) } } @Test fun testSinh() = DoubleTensorAlgebra { - assertTrue { tensor.sinh() eq expectedTensor(::sinh) } + assertTrue { sinh(tensor) eq expectedTensor(::sinh) } } @Test fun testAsinh() = DoubleTensorAlgebra { - assertTrue { tensor.asinh() eq expectedTensor(::asinh) } + assertTrue { asinh(tensor) eq expectedTensor(::asinh) } } @Test fun testTan() = DoubleTensorAlgebra { - assertTrue { tensor.tan() eq expectedTensor(::tan) } + assertTrue { tan(tensor) eq expectedTensor(::tan) } } @Test fun testAtan() = DoubleTensorAlgebra { - assertTrue { tensor.atan() eq expectedTensor(::atan) } + assertTrue { atan(tensor) eq expectedTensor(::atan) } } @Test fun testTanh() = DoubleTensorAlgebra { - assertTrue { tensor.tanh() eq expectedTensor(::tanh) } + assertTrue { tanh(tensor) eq expectedTensor(::tanh) } } @Test fun testCeil() = DoubleTensorAlgebra { - assertTrue { tensor.ceil() eq expectedTensor(::ceil) } + assertTrue { ceil(tensor) eq expectedTensor(::ceil) } } @Test fun testFloor() = DoubleTensorAlgebra { - assertTrue { tensor.floor() eq expectedTensor(::floor) } + assertTrue { floor(tensor) eq expectedTensor(::floor) } } val shape2 = ShapeND(2, 2) @@ -163,15 +163,15 @@ internal class TestDoubleAnalyticTensorAlgebra { @Test fun testMean() = DoubleTensorAlgebra { - assertTrue { tensor2.mean() == 1.0 } + assertTrue { mean(tensor2) == 1.0 } assertTrue { - tensor2.mean(0, true) eq fromArray( + mean(tensor2, 0, true) eq fromArray( ShapeND(1, 2), doubleArrayOf(-1.0, 3.0) ) } assertTrue { - tensor2.mean(1, false) eq fromArray( + mean(tensor2, 1, false) eq fromArray( ShapeND(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 d47af4a64..cbd7b9887 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 @@ -35,7 +35,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { -7.0 ) ) - val detTensor = tensor.detLU() + val detTensor = detLU(tensor) assertTrue(detTensor.eq(expectedTensor)) @@ -88,7 +88,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - val invTensor = tensor.invLU() + val invTensor = invLU(tensor) assertTrue(invTensor.eq(expectedTensor)) } @@ -111,7 +111,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { val tensor = fromArray(shape, buffer) - val (q, r) = tensor.qr() + val (q, r) = qr(tensor) assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } @@ -131,7 +131,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) val tensor = fromArray(shape, buffer) - val (p, l, u) = tensor.lu() + val (p, l, u) = lu(tensor) assertTrue { p.shape contentEquals shape } assertTrue { l.shape contentEquals shape } @@ -146,7 +146,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( fromArray(ShapeND(2, 5), DoubleArray(10) { 0.1 }) ) - val low = sigma.cholesky() + val low = cholesky(sigma) val sigmChol = low matmul low.transposed() assertTrue(sigma.eq(sigmChol)) } @@ -171,7 +171,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(ShapeND(2, 5, 3), 0) - val (tensorU, tensorS, tensorV) = tensor.svd() + val (tensorU, tensorS, tensorV) = svd(tensor) val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) } @@ -180,7 +180,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSymEig() = DoubleTensorAlgebra { val tensor = randomNormal(shape = ShapeND(2, 3, 3), 0) val tensorSigma = tensor + tensor.transposed() - val (tensorS, tensorV) = tensorSigma.symEig() + val (tensorS, tensorV) = symEig(tensorSigma) val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } @@ -190,7 +190,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10) { - val svd = tensor.svd() + val svd = svd(tensor) val tensorSVD = svd.first .dot( From b14e2fdd083e26a7843e75ec35a0a5c5118a2d53 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 5 Nov 2022 21:44:41 +0300 Subject: [PATCH 19/72] Moved polynomials to https://github.com/SciProgCentre/kmath-polynomial --- CHANGELOG.md | 1 + examples/build.gradle.kts | 1 - .../kscience/kmath/functions/polynomials.kt | 399 - kmath-polynomial/README.md | 50 - kmath-polynomial/build.gradle.kts | 69 - .../kmath/functions/LabeledPolynomial.kt | 529 - .../functions/LabeledRationalFunction.kt | 92 - .../kmath/functions/ListPolynomial.kt | 374 - .../kmath/functions/ListRationalFunction.kt | 123 - .../kmath/functions/NumberedPolynomial.kt | 350 - .../functions/NumberedRationalFunction.kt | 225 - .../kscience/kmath/functions/Polynomial.kt | 527 - .../kmath/functions/RationalFunction.kt | 1689 --- .../kscience/kmath/functions/algebraicStub.kt | 146 - .../kmath/functions/collectionUtils.kt | 906 -- .../kmath/functions/labeledConstructors.kt | 779 - .../kscience/kmath/functions/labeledUtil.kt | 321 - .../kmath/functions/listConstructors.kt | 92 - .../kscience/kmath/functions/listUtil.kt | 255 - .../space/kscience/kmath/functions/misc.kt | 22 - .../kmath/functions/numberedConstructors.kt | 491 - .../kscience/kmath/functions/numberedUtil.kt | 513 - .../kmath/functions/AlgebraicStubTest.kt | 589 - .../functions/LabeledConstructorsTest.kt | 127 - .../kmath/functions/LabeledPolynomialTest.kt | 2555 ---- .../functions/LabeledPolynomialUtilTest.kt | 8222 ----------- .../kmath/functions/ListPolynomialTest.kt | 544 - .../kmath/functions/ListPolynomialUtilTest.kt | 982 -- .../functions/NumberedConstructorsTest.kt | 123 - .../kmath/functions/NumberedPolynomialTest.kt | 1740 --- .../functions/NumberedPolynomialUtilTest.kt | 12021 ---------------- .../kmath/functions/testUtils/BufferUtils.kt | 12 - .../kmath/functions/testUtils/IntModulo.kt | 133 - .../functions/testUtils/IntModuloUtils.kt | 19 - .../kmath/functions/testUtils/NTMisc.kt | 29 - .../kmath/functions/testUtils/Rational.kt | 177 - .../kmath/functions/testUtils/assertion.kt | 104 - .../kmath/functions/testUtils/misc.kt | 19 - settings.gradle.kts | 1 - 39 files changed, 1 insertion(+), 35350 deletions(-) delete mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt delete mode 100644 kmath-polynomial/README.md delete mode 100644 kmath-polynomial/build.gradle.kts delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt delete mode 100644 kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt delete mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index c31740a31..1b3ab75fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ ### Deprecated ### Removed +- Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial ### Fixed diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 1d224bace..da645f012 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -18,7 +18,6 @@ dependencies { 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")) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt deleted file mode 100644 index 8228983e2..000000000 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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/kmath-polynomial/README.md b/kmath-polynomial/README.md deleted file mode 100644 index a5078a7e0..000000000 --- a/kmath-polynomial/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# 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 deleted file mode 100644 index 4e469f0d1..000000000 --- a/kmath-polynomial/build.gradle.kts +++ /dev/null @@ -1,69 +0,0 @@ -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 deleted file mode 100644 index 662e8ca74..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 185782f22..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 3753a93c4..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index c2fa6b2ec..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index eaf5befb1..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 4109338fd..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 7140ba70e..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 766d9ce98..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ /dev/null @@ -1,1689 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 80bf6ec53..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index e294f3533..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 78bb3b290..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 188240bf7..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 30b1e2fe4..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index e7c11f5ea..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 0a251b3b7..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index df4afbd12..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 88424d23c..000000000 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 9dd2bb743..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 054f0dc4c..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index bb30f7742..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt +++ /dev/null @@ -1,2555 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 637981b66..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt +++ /dev/null @@ -1,8222 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 5f7e1a95b..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 48ea89a46..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index ad6240fb9..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index c2f86198c..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ /dev/null @@ -1,1740 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index e5d1ddf48..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ /dev/null @@ -1,12021 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index ab912a464..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index a037dcd18..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 615523873..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 61b50f128..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 0a3d00e96..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index c70c229ca..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 deleted file mode 100644 index 66e46c902..000000000 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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/settings.gradle.kts b/settings.gradle.kts index f53232f44..23af18d31 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,6 @@ include( ":kmath-core", ":kmath-coroutines", ":kmath-functions", - ":kmath-polynomial", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", From 991ab907d87536c636f2ab6830a0f4a28886c386 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 11:09:55 +0300 Subject: [PATCH 20/72] Encapsulate internal constants in Expression --- benchmarks/build.gradle.kts | 9 ++----- .../kscience/kmath/expressions/Expression.kt | 24 ++++++++++++------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 9c8dc613a..5d2e4dac8 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -50,6 +50,8 @@ kotlin { val jvmMain by getting { dependencies { + implementation("org.openjdk.jmh:jmh-core:1.36") + implementation("org.openjdk.jmh:jmh-generator-annprocess:1.36") implementation(project(":kmath-commons")) implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) @@ -144,13 +146,6 @@ benchmark { } } -// Fix kotlinx-benchmarks bug -afterEvaluate { - val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - } -} - kotlin.sourceSets.all { with(languageSettings) { optIn("kotlin.contracts.ExperimentalContracts") 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 9c769caa0..cf59efe71 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 @@ -48,6 +48,10 @@ public interface DoubleExpression : Expression { * @return the value. */ public operator fun invoke(arguments: DoubleArray): Double + + public companion object{ + internal val EMPTY_DOUBLE_ARRAY = DoubleArray(0) + } } /** @@ -73,6 +77,10 @@ public interface IntExpression : Expression { * @return the value. */ public operator fun invoke(arguments: IntArray): Int + + public companion object{ + internal val EMPTY_INT_ARRAY = IntArray(0) + } } /** @@ -98,6 +106,10 @@ public interface LongExpression : Expression { * @return the value. */ public operator fun invoke(arguments: LongArray): Long + + public companion object{ + internal val EMPTY_LONG_ARRAY = LongArray(0) + } } /** @@ -145,7 +157,7 @@ public operator fun Expression.invoke(vararg pairs: Pair): T = } ) -private val EMPTY_DOUBLE_ARRAY = DoubleArray(0) + /** * Calls this expression without providing any arguments. @@ -153,7 +165,7 @@ private val EMPTY_DOUBLE_ARRAY = DoubleArray(0) * @return a value. */ @UnstableKMathAPI -public operator fun DoubleExpression.invoke(): Double = this(EMPTY_DOUBLE_ARRAY) +public operator fun DoubleExpression.invoke(): Double = this(DoubleExpression.EMPTY_DOUBLE_ARRAY) /** * Calls this expression from arguments. @@ -164,15 +176,13 @@ public operator fun DoubleExpression.invoke(): Double = this(EMPTY_DOUBLE_ARRAY) @UnstableKMathAPI public operator fun DoubleExpression.invoke(vararg arguments: Double): Double = this(arguments) -private val EMPTY_INT_ARRAY = IntArray(0) - /** * Calls this expression without providing any arguments. * * @return a value. */ @UnstableKMathAPI -public operator fun IntExpression.invoke(): Int = this(EMPTY_INT_ARRAY) +public operator fun IntExpression.invoke(): Int = this(IntExpression.EMPTY_INT_ARRAY) /** * Calls this expression from arguments. @@ -183,15 +193,13 @@ public operator fun IntExpression.invoke(): Int = this(EMPTY_INT_ARRAY) @UnstableKMathAPI public operator fun IntExpression.invoke(vararg arguments: Int): Int = this(arguments) -private val EMPTY_LONG_ARRAY = LongArray(0) - /** * Calls this expression without providing any arguments. * * @return a value. */ @UnstableKMathAPI -public operator fun LongExpression.invoke(): Long = this(EMPTY_LONG_ARRAY) +public operator fun LongExpression.invoke(): Long = this(LongExpression.EMPTY_LONG_ARRAY) /** * Calls this expression from arguments. From 29977650f10d0d1168a4f218b2b71e371b567653 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 12:21:56 +0300 Subject: [PATCH 21/72] Naive classifier notebook --- .gitignore | 3 +- examples/notebooks/Naive classifier.ipynb | 418 ++++++++++++++++++++++ 2 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 examples/notebooks/Naive classifier.ipynb diff --git a/.gitignore b/.gitignore index 5ddd846a8..34ddf3fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,9 @@ build/ out/ .idea/ - - .vscode/ + # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar diff --git a/examples/notebooks/Naive classifier.ipynb b/examples/notebooks/Naive classifier.ipynb new file mode 100644 index 000000000..937f5b6c6 --- /dev/null +++ b/examples/notebooks/Naive classifier.ipynb @@ -0,0 +1,418 @@ +{ + "cells": [ + { + "cell_type": "code", + "source": [ + "%use kmath(0.3.1-dev-5)\n", + "%use plotly(0.5.0)\n", + "@file:DependsOn(\"space.kscience:kmath-commons:0.3.1-dev-5\")" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "lQbSB87rNAn9lV6poArVWW", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "//Uncomment to work in Jupyter classic or DataLore\n", + "//Plotly.jupyter.notebook()" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "0UP158hfccGgjQtHz0wAi6", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "# The model\n", + "\n", + "Defining the input data format, the statistic abstraction and the statistic implementation based on a weighted sum of elements." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "class XYValues(val xValues: DoubleArray, val yValues: DoubleArray) {\n", + " init {\n", + " require(xValues.size == yValues.size)\n", + " }\n", + "}\n", + "\n", + "fun interface XYStatistic {\n", + " operator fun invoke(values: XYValues): Double\n", + "}\n", + "\n", + "class ConvolutionalXYStatistic(val weights: DoubleArray) : XYStatistic {\n", + " override fun invoke(values: XYValues): Double {\n", + " require(weights.size == values.yValues.size)\n", + " val norm = values.yValues.sum()\n", + " return values.yValues.zip(weights) { value, weight -> value * weight }.sum()/norm\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "Zhgz1Ui91PWz0meJiQpHol", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "# Generator\n", + "Generate sample data for parabolas and hyperbolas" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "fun generateParabolas(xValues: DoubleArray, a: Double, b: Double, c: Double): XYValues {\n", + " val yValues = xValues.map { x -> a * x * x + b * x + c }.toDoubleArray()\n", + " return XYValues(xValues, yValues)\n", + "}\n", + "\n", + "fun generateHyperbols(xValues: DoubleArray, gamma: Double, x0: Double, y0: Double): XYValues {\n", + " val yValues = xValues.map { x -> y0 + gamma / (x - x0) }.toDoubleArray()\n", + " return XYValues(xValues, yValues)\n", + "}" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "val xValues = (1.0..10.0).step(1.0).toDoubleArray()\n", + "\n", + "val xy = generateHyperbols(xValues, 1.0, 0.0, 0.0)\n", + "\n", + "Plotly.plot {\n", + " scatter {\n", + " this.x.doubles = xValues\n", + " this.y.doubles = xy.yValues\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "ZE2atNvFzQsCvpAF8KK4ch", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Create a default statistic with uniform weights" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "val statistic = ConvolutionalXYStatistic(DoubleArray(xValues.size){1.0})\n", + "statistic(xy)" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "EA5HaydTddRKYrtAUwd29h", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "import kotlin.random.Random\n", + "\n", + "val random = Random(1288)\n", + "\n", + "val parabolas = buildList{\n", + " repeat(500){\n", + " add(\n", + " generateParabolas(\n", + " xValues, \n", + " random.nextDouble(), \n", + " random.nextDouble(), \n", + " random.nextDouble()\n", + " )\n", + " )\n", + " }\n", + "}\n", + "\n", + "val hyperbolas: List = buildList{\n", + " repeat(500){\n", + " add(\n", + " generateHyperbols(\n", + " xValues, \n", + " random.nextDouble()*10, \n", + " random.nextDouble(), \n", + " random.nextDouble()\n", + " )\n", + " )\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "t5t6IYmD7Q1ykeo9uijFfQ", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "Plotly.plot { \n", + " scatter { \n", + " x.doubles = xValues\n", + " y.doubles = parabolas[257].yValues\n", + " }\n", + " scatter { \n", + " x.doubles = xValues\n", + " y.doubles = hyperbolas[252].yValues\n", + " }\n", + " }" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "oXB8lmju7YVYjMRXITKnhO", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "Plotly.plot { \n", + " histogram { \n", + " name = \"parabolae\"\n", + " x.numbers = parabolas.map { statistic(it) }\n", + " }\n", + " histogram { \n", + " name = \"hyperbolae\"\n", + " x.numbers = hyperbolas.map { statistic(it) }\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "8EIIecUZrt2NNrOkhxG5P0", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "val lossFunction: (XYStatistic) -> Double = { statistic ->\n", + " - abs(parabolas.sumOf { statistic(it) } - hyperbolas.sumOf { statistic(it) })\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "h7UmglJW5zXkAfKHK40oIL", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Using commons-math optimizer to optimize weights" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "import org.apache.commons.math3.optim.*\n", + "import org.apache.commons.math3.optim.nonlinear.scalar.*\n", + "import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.*\n", + "\n", + "val optimizer = SimplexOptimizer(1e-1, Double.MAX_VALUE)\n", + "\n", + "val result = optimizer.optimize(\n", + " ObjectiveFunction { point ->\n", + " lossFunction(ConvolutionalXYStatistic(point))\n", + " },\n", + " NelderMeadSimplex(xValues.size),\n", + " InitialGuess(DoubleArray(xValues.size){ 1.0 }),\n", + " GoalType.MINIMIZE,\n", + " MaxEval(100000)\n", + ")" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "0EG3K4aCUciMlgGQKPvJ57", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Print resulting weights of optimization" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "result.point" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "LelUlY0ZSlJEO9yC6SLk5B", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "source": [ + "Plotly.plot { \n", + " scatter { \n", + " y.doubles = result.point\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "AuFOq5t9KpOIkGrOLsVXNf", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "markdown", + "source": [ + "# The resulting statistic distribution" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "source": [ + "val resultStatistic = ConvolutionalXYStatistic(result.point)\n", + "Plotly.plot { \n", + " histogram { \n", + " name = \"parabolae\"\n", + " x.numbers = parabolas.map { resultStatistic(it) }\n", + " }\n", + " histogram { \n", + " name = \"hyperbolae\"\n", + " x.numbers = hyperbolas.map { resultStatistic(it) }\n", + " }\n", + "}" + ], + "execution_count": null, + "outputs": [], + "metadata": { + "datalore": { + "node_id": "zvmq42DRdM5mZ3SpzviHwI", + "type": "CODE", + "hide_input_from_viewers": false, + "hide_output_from_viewers": false + } + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Kotlin", + "language": "kotlin", + "name": "kotlin" + }, + "datalore": { + "version": 1, + "computation_mode": "JUPYTER", + "package_manager": "pip", + "base_environment": "default", + "packages": [] + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 6d47c0ccecd4068cc4c6289741d5dc89931c4a13 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 12:30:15 +0300 Subject: [PATCH 22/72] Ordered segments in trajectory --- .../kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 3fcf4365d..ffa23a537 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -102,7 +102,7 @@ public data class CircleTrajectory2D( } } -public open class CompositeTrajectory2D(public val segments: Collection) : Trajectory2D { +public open class CompositeTrajectory2D(public val segments: List) : Trajectory2D { override val length: Double get() = segments.sumOf { it.length } } From 3f4fe9e43ba488b5d5de65aaf9b916159023724e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 31 Dec 2022 15:02:52 +0300 Subject: [PATCH 23/72] Migrate to 1.8. Use universal autodiffs --- benchmarks/build.gradle.kts | 4 +- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 13 +++-- buildSrc/settings.gradle.kts | 2 +- .../kscience/kmath/benchmarks/JmhReport.kt | 5 -- .../benchmarks/addBenchmarkProperties.kt | 9 ++-- .../space/kscience/kmath/fit/chiSquared.kt | 4 +- .../kotlin/space/kscience/kmath/fit/qowFit.kt | 4 +- .../kmath/stat/DistributionBenchmark.kt | 4 +- gradle.properties | 3 +- gradle/wrapper/gradle-wrapper.properties | 2 +- ...ructureExpression.kt => CmDsExpression.kt} | 19 ++++--- .../DerivativeStructureExpressionTest.kt | 8 +-- .../commons/optimization/OptimizeTest.kt | 11 ++-- .../kscience/kmath/expressions/DSAlgebra.kt | 51 +++++++++++-------- .../kscience/kmath/expressions/DSCompiler.kt | 2 - .../kscience/kmath/expressions/DSTest.kt | 5 +- kmath-functions/build.gradle.kts | 2 +- kmath-histograms/build.gradle.kts | 2 +- kmath-optimization/build.gradle.kts | 2 +- kmath-stat/build.gradle.kts | 2 +- settings.gradle.kts | 2 +- 22 files changed, 84 insertions(+), 74 deletions(-) rename kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/{DerivativeStructureExpression.kt => CmDsExpression.kt} (91%) diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 5d2e4dac8..ea2349d91 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -5,7 +5,7 @@ import space.kscience.kmath.benchmarks.addBenchmarkProperties plugins { kotlin("multiplatform") - kotlin("plugin.allopen") + alias(spclibs.plugins.kotlin.plugin.allopen) id("org.jetbrains.kotlinx.benchmark") } @@ -44,7 +44,7 @@ kotlin { implementation(project(":kmath-tensors")) implementation(project(":kmath-multik")) implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") - implementation(npmlibs.kotlinx.benchmark.runtime) + implementation(spclibs.kotlinx.benchmark.runtime) } } diff --git a/build.gradle.kts b/build.gradle.kts index e03bec9af..4efb6c802 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-7" + version = "0.3.1-dev-8" } subprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 0f95a7b3f..67df0aab4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,7 +1,6 @@ plugins { `kotlin-dsl` `version-catalog` - kotlin("plugin.serialization") version "1.6.21" } java.targetCompatibility = JavaVersion.VERSION_11 @@ -13,18 +12,18 @@ repositories { gradlePluginPortal() } -val toolsVersion = npmlibs.versions.tools.get() -val kotlinVersion = npmlibs.versions.kotlin.asProvider().get() -val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get() +val toolsVersion = spclibs.versions.tools.get() +val kotlinVersion = spclibs.versions.kotlin.asProvider().get() +val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get() dependencies { 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") + //api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //to be used inside build-script only - implementation(npmlibs.kotlinx.serialization.json) + //implementation(spclibs.kotlinx.serialization.json) + implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+") } kotlin.sourceSets.all { diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 403e0f52c..02111ba37 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -26,7 +26,7 @@ dependencyResolutionManagement { } versionCatalogs { - create("npmlibs") { + create("spclibs") { 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 62cf44915..3a4fcdc79 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt @@ -5,9 +5,6 @@ package space.kscience.kmath.benchmarks -import kotlinx.serialization.Serializable - -@Serializable data class JmhReport( val jmhVersion: String, val benchmark: String, @@ -37,7 +34,6 @@ data class JmhReport( val scoreUnit: String } - @Serializable data class PrimaryMetric( override val score: Double, override val scoreError: Double, @@ -48,7 +44,6 @@ data class JmhReport( val rawData: List>? = null, ) : Metric - @Serializable data class SecondaryMetric( override val score: Double, override val scoreError: Double, 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 5c6a2ac83..61193790b 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.benchmarks import kotlinx.benchmark.gradle.BenchmarksExtension -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue import org.gradle.api.Project import space.kscience.gradle.KScienceReadmeExtension import java.time.LocalDateTime @@ -45,6 +45,8 @@ private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run { private fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural +private val jsonMapper = jacksonObjectMapper() + fun Project.addBenchmarkProperties() { val benchmarksProject = this rootProject.subprojects.forEach { p -> @@ -60,8 +62,7 @@ fun Project.addBenchmarkProperties() { if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) { "> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**." } else { - val reports = - Json.decodeFromString>(resDirectory.resolve("jvm.json").readText()) + val reports: List = jsonMapper.readValue>(resDirectory.resolve("jvm.json")) buildString { appendLine("

") 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 febf55283..c5f694ce0 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -7,9 +7,9 @@ package space.kscience.kmath.fit import kotlinx.html.br import kotlinx.html.h3 -import space.kscience.kmath.commons.expressions.DSProcessor import space.kscience.kmath.commons.optimization.CMOptimizer import space.kscience.kmath.distributions.NormalDistribution +import space.kscience.kmath.expressions.autodiff import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.asIterable @@ -67,7 +67,7 @@ suspend fun main() { val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma) // compute differentiable chi^2 sum for given model ax^2 + bx + c - val chi2 = DSProcessor.chiSquaredExpression(x, y, yErr) { arg -> + val chi2 = Double.autodiff.chiSquaredExpression(x, y, yErr) { arg -> //bind variables to autodiff context val a = bindSymbol(a) val b = bindSymbol(b) 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 c7eefa6b9..9650fa630 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -7,10 +7,10 @@ package space.kscience.kmath.fit import kotlinx.html.br import kotlinx.html.h3 -import space.kscience.kmath.commons.expressions.DSProcessor import space.kscience.kmath.data.XYErrorColumnarData import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.autodiff import space.kscience.kmath.expressions.binding import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.asIterable @@ -63,7 +63,7 @@ suspend fun main() { val result = XYErrorColumnarData.of(x, y, yErr).fitWith( QowOptimizer, - DSProcessor, + Double.autodiff, mapOf(a to 0.9, b to 1.2, c to 2.0) ) { arg -> //bind variables to autodiff context 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 2576e9222..031955e15 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -36,7 +36,7 @@ private suspend fun runKMathChained(): Duration { return Duration.between(startTime, Instant.now()) } -private fun runApacheDirect(): Duration { +private fun runCMDirect(): Duration { val rng = RandomSource.create(RandomSource.MT, 123L) val sampler = CMGaussianSampler.of( @@ -65,7 +65,7 @@ private fun runApacheDirect(): Duration { * Comparing chain sampling performance with direct sampling performance */ fun main(): Unit = runBlocking(Dispatchers.Default) { - val directJob = async { runApacheDirect() } + val directJob = async { runCMDirect() } val chainJob = async { runKMathChained() } println("KMath Chained: ${chainJob.await()}") println("Apache Direct: ${directJob.await()}") diff --git a/gradle.properties b/gradle.properties index da5867ea4..3016246b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,12 +5,11 @@ kotlin.code.style=official kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -kotlin.incremental.js.ir=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.13.1-kotlin-1.7.20 +toolsVersion=0.13.4-kotlin-1.8.0 org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684f..070cb702f 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.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists 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/CmDsExpression.kt similarity index 91% rename from kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt rename to kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/CmDsExpression.kt index 6d756b15f..f2af49087 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/CmDsExpression.kt @@ -18,7 +18,8 @@ import space.kscience.kmath.operations.NumbersAddOps * @param bindings The map of bindings values. All bindings are considered free parameters */ @OptIn(UnstableKMathAPI::class) -public class DerivativeStructureField( +@Deprecated("Use generic DSAlgebra from the core") +public class CmDsField( public val order: Int, bindings: Map, ) : ExtendedField, ExpressionAlgebra, @@ -108,25 +109,27 @@ public class DerivativeStructureField( /** * Auto-diff processor based on Commons-math [DerivativeStructure] */ -public object DSProcessor : AutoDiffProcessor { +@Deprecated("Use generic DSAlgebra from the core") +public object CmDsProcessor : AutoDiffProcessor { override fun differentiate( - function: DerivativeStructureField.() -> DerivativeStructure, - ): DerivativeStructureExpression = DerivativeStructureExpression(function) + function: CmDsField.() -> DerivativeStructure, + ): CmDsExpression = CmDsExpression(function) } /** * A constructs that creates a derivative structure with required order on-demand */ -public class DerivativeStructureExpression( - public val function: DerivativeStructureField.() -> DerivativeStructure, +@Deprecated("Use generic DSAlgebra from the core") +public class CmDsExpression( + public val function: CmDsField.() -> DerivativeStructure, ) : DifferentiableExpression { override operator fun invoke(arguments: Map): Double = - DerivativeStructureField(0, arguments).function().value + CmDsField(0, arguments).function().value /** * Get the derivative expression with given orders */ override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> - with(DerivativeStructureField(symbols.size, arguments)) { function().derivative(symbols) } + with(CmDsField(symbols.size, arguments)) { function().derivative(symbols) } } } 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 40ba9fc7d..7c3c086ed 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 @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("DEPRECATION") + package space.kscience.kmath.commons.expressions import space.kscience.kmath.expressions.* @@ -15,10 +17,10 @@ import kotlin.test.assertFails internal inline fun diff( order: Int, vararg parameters: Pair, - block: DerivativeStructureField.() -> Unit, + block: CmDsField.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - DerivativeStructureField(order, mapOf(*parameters)).run(block) + CmDsField(order, mapOf(*parameters)).run(block) } internal class AutoDiffTest { @@ -41,7 +43,7 @@ internal class AutoDiffTest { @Test fun autoDifTest() { - val f = DerivativeStructureExpression { + val f = CmDsExpression { val x by binding val y by binding x.pow(2) + 2 * x * y + y.pow(2) + 1 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 7c8ba7d27..8b4631fca 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 @@ -6,22 +6,25 @@ package space.kscience.kmath.commons.optimization import kotlinx.coroutines.runBlocking -import space.kscience.kmath.commons.expressions.DSProcessor -import space.kscience.kmath.commons.expressions.DerivativeStructureExpression import space.kscience.kmath.distributions.NormalDistribution +import space.kscience.kmath.expressions.DSFieldExpression import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.y +import space.kscience.kmath.expressions.autodiff import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleBufferOps.Companion.map +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.optimization.* import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import kotlin.test.Test +@OptIn(UnstableKMathAPI::class) internal class OptimizeTest { - val normal = DerivativeStructureExpression { + val normal = DSFieldExpression(DoubleField) { exp(-bindSymbol(x).pow(2) / 2) + exp(-bindSymbol(y).pow(2) / 2) } @@ -60,7 +63,7 @@ internal class OptimizeTest { val yErr = DoubleBuffer(x.size) { sigma } - val chi2 = DSProcessor.chiSquaredExpression( + val chi2 = Double.autodiff.chiSquaredExpression( x, y, yErr ) { arg -> val cWithDefault = bindSymbolOrNull(c) ?: one 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 index e7ade4f66..9e91ff26b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt @@ -80,7 +80,6 @@ public abstract class DSAlgebra>( public val algebra: A, public val order: Int, bindings: Map, - public val valueBufferFactory: MutableBufferFactory = algebra.bufferFactory, ) : ExpressionAlgebra>, SymbolIndexer { /** @@ -116,7 +115,6 @@ public abstract class DSAlgebra>( newCache[p][o] = DSCompiler( algebra, - valueBufferFactory, p, o, valueCompiler, @@ -141,7 +139,7 @@ public abstract class DSAlgebra>( override val symbols: List = bindings.map { it.key } private fun bufferForVariable(index: Int, value: T): Buffer { - val buffer = valueBufferFactory(compiler.size) { algebra.zero } + val buffer = algebra.bufferFactory(compiler.size) { algebra.zero } buffer[0] = value if (compiler.order > 0) { // the derivative of the variable with respect to itself is 1. @@ -207,7 +205,7 @@ public abstract class DSAlgebra>( } public override fun const(value: T): DS { - val buffer = valueBufferFactory(compiler.size) { algebra.zero } + val buffer = algebra.bufferFactory(compiler.size) { algebra.zero } buffer[0] = value return DS(buffer) @@ -245,11 +243,14 @@ public open class DSRing( algebra: A, order: Int, bindings: Map, - valueBufferFactory: MutableBufferFactory, -) : DSAlgebra(algebra, order, bindings, valueBufferFactory), - Ring>, ScaleOperations>, +) : DSAlgebra(algebra, order, bindings), + Ring>, + ScaleOperations>, NumericAlgebra>, - NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { + NumbersAddOps> + where A : Ring, A : NumericAlgebra, A : ScaleOperations { + + public val elementBufferFactory: MutableBufferFactory = algebra.bufferFactory override fun bindSymbolOrNull(value: String): DSSymbol? = super.bindSymbolOrNull(value) @@ -261,14 +262,14 @@ public open class DSRing( */ 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] } + val newData = elementBufferFactory(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.mapToBuffer(valueBufferFactory) { + val newData: Buffer = data.mapToBuffer(elementBufferFactory) { algebra.block(it) } return DS(newData) @@ -276,7 +277,7 @@ public open class DSRing( 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.mapIndexedToBuffer(valueBufferFactory, block) + val newData: Buffer = data.mapIndexedToBuffer(elementBufferFactory, block) return DS(newData) } @@ -329,22 +330,21 @@ public class DerivativeStructureRingExpression( 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 + DSRing(algebra, 0, arguments).function().value override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> with( DSRing( algebra, symbols.size, - arguments, - elementBufferFactory + arguments ) ) { function().derivative(symbols) } } } /** - * A field over commons-math [DerivativeStructure]. + * A field over [DS]. * * @property order The derivation order. * @param bindings The map of bindings values. All bindings are considered free parameters. @@ -354,8 +354,7 @@ public class DSField>( algebra: A, order: Int, bindings: Map, - valueBufferFactory: MutableBufferFactory, -) : DSRing(algebra, order, bindings, valueBufferFactory), ExtendedField> { +) : DSRing(algebra, order, bindings), ExtendedField> { override fun number(value: Number): DS = const(algebra.number(value)) override fun divide(left: DS, right: DS): DS = left.transformDataBuffer { result -> @@ -414,6 +413,7 @@ public class DSField>( 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) } @@ -439,18 +439,29 @@ public class DSField>( @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 + DSField(algebra, 0, arguments).function().value override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> DSField( algebra, symbols.size, arguments, - valueBufferFactory, ).run { function().derivative(symbols) } } } + + +@UnstableKMathAPI +public class DSFieldProcessor>( + public val algebra: A, +) : AutoDiffProcessor, DSField> { + override fun differentiate( + function: DSField.() -> DS, + ): DifferentiableExpression = DSFieldExpression(algebra, function) +} + +@UnstableKMathAPI +public val Double.Companion.autodiff: DSFieldProcessor get() = DSFieldProcessor(DoubleField) \ No newline at end of file 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 index 6ab9b3d44..1da151d46 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt @@ -9,7 +9,6 @@ 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) { @@ -56,7 +55,6 @@ internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: */ public class DSCompiler> internal constructor( public val algebra: A, - public val bufferFactory: MutableBufferFactory, public val freeParameters: Int, public val order: Int, valueCompiler: DSCompiler?, 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 index f46f3023d..0bfcb04a7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt @@ -9,7 +9,6 @@ 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 @@ -22,7 +21,7 @@ internal inline fun diff( block: DSField.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - DSField(DoubleField, order, mapOf(*parameters), ::DoubleBuffer).block() + DSField(DoubleField, order, mapOf(*parameters)).block() } internal class DSTest { @@ -45,7 +44,7 @@ internal class DSTest { @Test fun dsExpressionTest() { - val f = DSFieldExpression(DoubleField, ::DoubleBuffer) { + val f = DSFieldExpression(DoubleField) { val x by binding val y by binding x.pow(2) + 2 * x * y + y.pow(2) + 1 diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 2e7b023c1..9c2cd8352 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -17,7 +17,7 @@ kotlin.sourceSets { } dependencies { - dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${npmlibs.versions.dokka.get()}") + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${spclibs.versions.dokka.get()}") } readme { diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index d31526a74..9d7ac33e4 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -12,7 +12,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-core")) - api(npmlibs.atomicfu) + api(spclibs.atomicfu) } } commonTest { diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index f4256b9aa..ba49d49bf 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -14,7 +14,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) - api(npmlibs.atomicfu) + api(spclibs.atomicfu) } } } diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index f6ca54e17..bc98129a9 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -10,7 +10,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) - implementation(npmlibs.atomicfu) + implementation(spclibs.atomicfu) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 23af18d31..7d92dc36e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,7 +13,7 @@ dependencyResolutionManagement { } versionCatalogs { - create("npmlibs") { + create("spclibs") { from("space.kscience:version-catalog:$toolsVersion") } } From 2e4be2aa3a3678ee5fed7de029106bb793ed4c32 Mon Sep 17 00:00:00 2001 From: darksnake Date: Tue, 24 Jan 2023 11:36:53 +0300 Subject: [PATCH 24/72] A minor change to XYfit arguments --- .../kscience/kmath/optimization/XYFit.kt | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) 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 d2182e91f..bba7a7113 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 @@ -30,7 +30,7 @@ public interface PointToCurveDistance : OptimizationFeature { return object : DifferentiableExpression { override fun derivativeOrNull( - symbols: List + symbols: List, ): Expression? = problem.model.derivativeOrNull(symbols)?.let { derivExpression -> Expression { arguments -> derivExpression.invoke(arguments + (Symbol.x to x)) @@ -93,24 +93,15 @@ public fun XYFit.withFeature(vararg features: OptimizationFeature): XYFit { return XYFit(data, model, this.features.with(*features), pointToCurveDistance, pointWeight) } -/** - * Fit given dta with - */ -public suspend fun XYColumnarData.fitWith( +public suspend fun XYColumnarData.fitWith( optimizer: Optimizer, - processor: AutoDiffProcessor, + modelExpression: DifferentiableExpression, startingPoint: Map, vararg features: OptimizationFeature = emptyArray(), xSymbol: Symbol = Symbol.x, pointToCurveDistance: PointToCurveDistance = PointToCurveDistance.byY, pointWeight: PointWeight = PointWeight.byYSigma, - model: A.(I) -> I -): XYFit where A : ExtendedField, A : ExpressionAlgebra { - val modelExpression = processor.differentiate { - val x = bindSymbol(xSymbol) - model(x) - } - +): XYFit { var actualFeatures = FeatureSet.of(*features, OptimizationStartPoint(startingPoint)) if (actualFeatures.getFeature() == null) { @@ -127,20 +118,50 @@ public suspend fun XYColumnarData.fitWith( return optimizer.optimize(problem) } +/** + * Fit given data with a model provided as an expression + */ +public suspend fun XYColumnarData.fitWith( + optimizer: Optimizer, + processor: AutoDiffProcessor, + startingPoint: Map, + vararg features: OptimizationFeature = emptyArray(), + xSymbol: Symbol = Symbol.x, + pointToCurveDistance: PointToCurveDistance = PointToCurveDistance.byY, + pointWeight: PointWeight = PointWeight.byYSigma, + model: A.(I) -> I, +): XYFit where A : ExtendedField, A : ExpressionAlgebra { + val modelExpression: DifferentiableExpression = processor.differentiate { + val x = bindSymbol(xSymbol) + model(x) + } + + return fitWith( + optimizer = optimizer, + modelExpression = modelExpression, + startingPoint = startingPoint, + features = features, + xSymbol = xSymbol, + pointToCurveDistance = pointToCurveDistance, + pointWeight = pointWeight + ) +} + /** * Compute chi squared value for completed fit. Return null for incomplete fit */ -public val XYFit.chiSquaredOrNull: Double? get() { - val result = resultPointOrNull ?: return null +public val XYFit.chiSquaredOrNull: Double? + get() { + val result = resultPointOrNull ?: return null - return data.indices.sumOf { index-> + return data.indices.sumOf { index -> - val x = data.x[index] - val y = data.y[index] - val yErr = data[Symbol.yError]?.get(index) ?: 1.0 + val x = data.x[index] + val y = data.y[index] + val yErr = data[Symbol.yError]?.get(index) ?: 1.0 - val mu = model.invoke(result + (xSymbol to x) ) + val mu = model.invoke(result + (xSymbol to x)) - ((y - mu)/yErr).pow(2) - } -} \ No newline at end of file + ((y - mu) / yErr).pow(2) + } + } \ No newline at end of file From 7f4f4c7703275e80cb51e38af3a28a7672dbbf5f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 24 Jan 2023 21:01:26 +0300 Subject: [PATCH 25/72] Update of symbolic operations --- CHANGELOG.md | 2 + build.gradle.kts | 2 +- .../space/kscience/kmath/fit/chiSquared.kt | 2 +- .../kotlin/space/kscience/kmath/fit/qowFit.kt | 21 ++-- .../expressions/ExpressionWithDefault.kt | 31 +++++ .../kscience/kmath/expressions/NamedMatrix.kt | 37 ++++++ .../kmath/optimization/OptimizationProblem.kt | 17 ++- .../kmath/optimization/QowOptimizer.kt | 116 ++++++++++-------- .../kscience/kmath/optimization/XYFit.kt | 7 +- .../kmath/stat/chiSquaredExpression.kt | 7 +- 10 files changed, 173 insertions(+), 69 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/ExpressionWithDefault.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt => kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/chiSquaredExpression.kt (87%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b3ab75fd..b8cb0d976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] ### Added +- `NamedMatrix` - matrix with symbol-based indexing +- `Expression` with default arguments - Type-aliases for numbers like `Float64` - 2D optimal trajectory computation in a separate module `kmath-trajectory` - Autodiff for generic algebra elements in core! diff --git a/build.gradle.kts b/build.gradle.kts index 4efb6c802..8731dbc70 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-8" + version = "0.3.1-dev-9" } subprojects { 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 c5f694ce0..258ed0c84 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -10,7 +10,6 @@ import kotlinx.html.h3 import space.kscience.kmath.commons.optimization.CMOptimizer import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.expressions.autodiff -import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.toList @@ -22,6 +21,7 @@ import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step +import space.kscience.kmath.stat.chiSquaredExpression import space.kscience.plotly.* import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.TraceValues 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 9650fa630..fe7f48b72 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -15,10 +15,7 @@ import space.kscience.kmath.expressions.binding import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.toList -import space.kscience.kmath.optimization.QowOptimizer -import space.kscience.kmath.optimization.chiSquaredOrNull -import space.kscience.kmath.optimization.fitWith -import space.kscience.kmath.optimization.resultPoint +import space.kscience.kmath.optimization.* import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.real.map import space.kscience.kmath.real.step @@ -32,6 +29,8 @@ import kotlin.math.sqrt private val a by symbol private val b by symbol private val c by symbol +private val d by symbol +private val e by symbol /** @@ -64,16 +63,22 @@ suspend fun main() { val result = XYErrorColumnarData.of(x, y, yErr).fitWith( QowOptimizer, Double.autodiff, - mapOf(a to 0.9, b to 1.2, c to 2.0) + mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0), + OptimizationParameters(a, b, c, d) ) { arg -> //bind variables to autodiff context val a by binding val b by binding //Include default value for c if it is not provided as a parameter val c = bindSymbolOrNull(c) ?: one - a * arg.pow(2) + b * arg + c + val d by binding + val e by binding + + a * arg.pow(2) + b * arg + c + d * arg.pow(3) + e / arg } + println("Resulting chi2/dof: ${result.chiSquaredOrNull}/${result.dof}") + //display a page with plot and numerical results val page = Plotly.page { plot { @@ -89,7 +94,7 @@ suspend fun main() { scatter { mode = ScatterMode.lines x(x) - y(x.map { result.model(result.resultPoint + (Symbol.x to it)) }) + y(x.map { result.model(result.startPoint + result.resultPoint + (Symbol.x to it)) }) name = "fit" } } @@ -98,7 +103,7 @@ suspend fun main() { +"Fit result: ${result.resultPoint}" } h3 { - +"Chi2/dof = ${result.chiSquaredOrNull!! / (x.size - 3)}" + +"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}" } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/ExpressionWithDefault.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/ExpressionWithDefault.kt new file mode 100644 index 000000000..c802fe04c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/ExpressionWithDefault.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2018-2023 KMath 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 + +public class ExpressionWithDefault( + private val origin: Expression, + private val defaultArgs: Map, +) : Expression { + override fun invoke(arguments: Map): T = origin.invoke(defaultArgs + arguments) +} + +public fun Expression.withDefaultArgs(defaultArgs: Map): ExpressionWithDefault = + ExpressionWithDefault(this, defaultArgs) + + +public class DiffExpressionWithDefault( + private val origin: DifferentiableExpression, + private val defaultArgs: Map, +) : DifferentiableExpression { + + override fun invoke(arguments: Map): T = origin.invoke(defaultArgs + arguments) + + override fun derivativeOrNull(symbols: List): Expression? = + origin.derivativeOrNull(symbols)?.withDefaultArgs(defaultArgs) +} + +public fun DifferentiableExpression.withDefaultArgs(defaultArgs: Map): DiffExpressionWithDefault = + DiffExpressionWithDefault(this, defaultArgs) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt new file mode 100644 index 000000000..f0b27ffa2 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2018-2023 KMath 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.linear.Matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.structures.getOrNull + +public class NamedMatrix(public val values: Matrix, public val indexer: SymbolIndexer) : Matrix by values { + public operator fun get(i: Symbol, j: Symbol): T = get(indexer.indexOf(i), indexer.indexOf(j)) + + public companion object { + + public fun toStringWithSymbols(values: Matrix<*>, indexer: SymbolIndexer): String = buildString { + appendLine(indexer.symbols.joinToString(separator = "\t", prefix = "\t\t")) + indexer.symbols.forEach { i -> + append(i.identity + "\t") + values.rows.getOrNull(indexer.indexOf(i))?.let { row -> + indexer.symbols.forEach { j -> + append(row.getOrNull(indexer.indexOf(j)).toString()) + append("\t") + } + appendLine() + } + } + } + } +} + +public fun Matrix.named(indexer: SymbolIndexer): NamedMatrix = NamedMatrix(this, indexer) + +public fun Matrix.named(symbols: List): NamedMatrix = named(SimpleSymbolIndexer(symbols)) \ No newline at end of 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 db154be42..9fdcfc53d 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.optimization import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.NamedMatrix import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.linear.Matrix import space.kscience.kmath.misc.* import kotlin.reflect.KClass @@ -32,7 +32,10 @@ public interface OptimizationPrior : OptimizationFeature, DifferentiableExpre override val key: FeatureKey get() = OptimizationPrior::class } -public class OptimizationCovariance(public val covariance: Matrix) : OptimizationFeature { +/** + * Covariance matrix for + */ +public class OptimizationCovariance(public val covariance: NamedMatrix) : OptimizationFeature { override fun toString(): String = "Covariance($covariance)" } @@ -57,10 +60,20 @@ public class OptimizationLog(private val loggable: Loggable) : Loggable by logga override fun toString(): String = "Log($loggable)" } +/** + * Free parameters of the optimization + */ public class OptimizationParameters(public val symbols: List) : OptimizationFeature { public constructor(vararg symbols: Symbol) : this(listOf(*symbols)) override fun toString(): String = "Parameters($symbols)" } +/** + * Maximum allowed number of iterations + */ +public class OptimizationIterations(public val maxIterations: Int) : OptimizationFeature { + override fun toString(): String = "Iterations($maxIterations)" +} + 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 669860934..bbebec6af 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 @@ -5,10 +5,7 @@ package space.kscience.kmath.optimization -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.expressions.SymbolIndexer -import space.kscience.kmath.expressions.derivative +import space.kscience.kmath.expressions.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.log @@ -16,6 +13,7 @@ import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleL2Norm import space.kscience.kmath.operations.algebra import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.abs public class QowRuns(public val runs: Int) : OptimizationFeature { @@ -40,18 +38,24 @@ public object QowOptimizer : Optimizer { @OptIn(UnstableKMathAPI::class) private class QoWeight( val problem: XYFit, - val parameters: Map, - ) : Map by parameters, SymbolIndexer { - override val symbols: List = parameters.keys.toList() + val freeParameters: Map, + ) : SymbolIndexer { + val size get() = freeParameters.size + + override val symbols: List = freeParameters.keys.toList() val data get() = problem.data + val allParameters by lazy { + problem.startPoint + freeParameters + } + /** * Derivatives of the spectrum over parameters. First index in the point number, second one - index of parameter */ val derivs: Matrix by lazy { linearSpace.buildMatrix(problem.data.size, symbols.size) { d, s -> - problem.distance(d).derivative(symbols[s])(parameters) + problem.distance(d).derivative(symbols[s]).invoke(allParameters) } } @@ -60,29 +64,31 @@ public object QowOptimizer : Optimizer { */ val dispersion: Point by lazy { DoubleBuffer(problem.data.size) { d -> - 1.0/problem.weight(d).invoke(parameters) + 1.0 / problem.weight(d).invoke(allParameters) } } - val prior: DifferentiableExpression? get() = problem.getFeature>() + val prior: DifferentiableExpression? + get() = problem.getFeature>()?.withDefaultArgs(allParameters) - override fun toString(): String = parameters.toString() + override fun toString(): String = freeParameters.toString() } /** * The signed distance from the model to the [d]-th point of data. */ - private fun QoWeight.distance(d: Int, parameters: Map): Double = problem.distance(d)(parameters) + private fun QoWeight.distance(d: Int, parameters: Map): Double = + problem.distance(d)(allParameters + parameters) /** * The derivative of [distance] */ private fun QoWeight.distanceDerivative(symbol: Symbol, d: Int, parameters: Map): Double = - problem.distance(d).derivative(symbol)(parameters) + problem.distance(d).derivative(symbol).invoke(allParameters + parameters) /** - * Теоретическая ковариация весовых функций. + * Theoretical covariance of weight functions * * D(\phi)=E(\phi_k(\theta_0) \phi_l(\theta_0))= disDeriv_k * disDeriv_l /sigma^2 */ @@ -92,7 +98,7 @@ public object QowOptimizer : Optimizer { } /** - * Экспериментальная ковариация весов. Формула (22) из + * Experimental covariance Eq (22) from * http://arxiv.org/abs/physics/0604127 */ private fun QoWeight.covarFExp(theta: Map): Matrix = @@ -115,10 +121,9 @@ public object QowOptimizer : Optimizer { * Equation derivatives for Newton run */ private fun QoWeight.getEqDerivValues( - theta: Map = parameters, + theta: Map = freeParameters, ): Matrix = with(linearSpace) { - //Возвращает производную k-того Eq по l-тому параметру - //val res = Array(fitDim) { DoubleArray(fitDim) } + //Derivative of k Eq over l parameter val sderiv = buildMatrix(data.size, size) { d, s -> distanceDerivative(symbols[s], d, theta) } @@ -140,16 +145,15 @@ public object QowOptimizer : Optimizer { /** - * Значения уравнений метода квазиоптимальных весов + * Quasi optimal weights equations values */ - private fun QoWeight.getEqValues(theta: Map = this): Point { + private fun QoWeight.getEqValues(theta: Map): Point { val distances = DoubleBuffer(data.size) { d -> distance(d, theta) } - return DoubleBuffer(size) { s -> val base = (0 until data.size).sumOf { d -> distances[d] * derivs[d, s] / dispersion[d] } - //Поправка на априорную вероятность + //Prior probability correction prior?.let { prior -> - base - prior.derivative(symbols[s])(theta) / prior(theta) + base - prior.derivative(symbols[s]).invoke(theta) / prior(theta) } ?: base } } @@ -157,15 +161,13 @@ public object QowOptimizer : Optimizer { private fun QoWeight.newtonianStep( theta: Map, - eqvalues: Point, + eqValues: Point, ): QoWeight = linearSpace { - with(this@newtonianStep) { - val start = theta.toPoint() - val invJacob = solver.inverse(this@newtonianStep.getEqDerivValues(theta)) + val start = theta.toPoint() + val invJacob = solver.inverse(getEqDerivValues(theta)) - val step = invJacob.dot(eqvalues) - return QoWeight(problem, theta + (start - step).toMap()) - } + val step = invJacob.dot(eqValues) + return QoWeight(problem, theta + (start - step).toMap()) } private fun QoWeight.newtonianRun( @@ -177,10 +179,10 @@ public object QowOptimizer : Optimizer { val logger = problem.getFeature() var dis: Double //discrepancy value - // Working with the full set of parameters - var par = problem.startPoint - logger?.log { "Starting newtonian iteration from: \n\t$par" } + var par = freeParameters + + logger?.log { "Starting newtonian iteration from: \n\t$allParameters" } var eqvalues = getEqValues(par) //Values of the weight functions @@ -193,48 +195,48 @@ public object QowOptimizer : Optimizer { logger?.log { "Starting step number $i" } val currentSolution = if (fast) { - //Берет значения матрицы в той точке, где считается вес - newtonianStep(this, eqvalues) + //Matrix values in the point of weight computation + newtonianStep(freeParameters, eqvalues) } else { - //Берет значения матрицы в точке par + //Matrix values in a current point newtonianStep(par, eqvalues) } // здесь должен стоять учет границ параметров logger?.log { "Parameter values after step are: \n\t$currentSolution" } - eqvalues = getEqValues(currentSolution) - val currentDis = DoubleL2Norm.norm(eqvalues)// невязка после шага + eqvalues = getEqValues(currentSolution.freeParameters) + val currentDis = DoubleL2Norm.norm(eqvalues)// discrepancy after the step logger?.log { "The discrepancy after step is: $currentDis." } if (currentDis >= dis && i > 1) { - //дополнительно проверяем, чтобы был сделан хотя бы один шаг + //Check if one step is made flag = true logger?.log { "The discrepancy does not decrease. Stopping iteration." } + } else if (abs(dis - currentDis) <= tolerance) { + flag = true + par = currentSolution.freeParameters + logger?.log { "Relative discrepancy tolerance threshold is reached. Stopping iteration." } } else { - par = currentSolution + par = currentSolution.freeParameters dis = currentDis } if (i >= maxSteps) { flag = true logger?.log { "Maximum number of iterations reached. Stopping iteration." } } - if (dis <= tolerance) { - flag = true - logger?.log { "Tolerance threshold is reached. Stopping iteration." } - } } return QoWeight(problem, par) } - private fun QoWeight.covariance(): Matrix { + private fun QoWeight.covariance(): NamedMatrix { val logger = problem.getFeature() logger?.log { """ - Starting errors estimation using quasioptimal weights method. The starting weight is: - ${problem.startPoint} + Starting errors estimation using quasi-optimal weights method. The starting weight is: + $allParameters """.trimIndent() } @@ -248,19 +250,27 @@ public object QowOptimizer : Optimizer { // valid = false // } // } - return covar + logger?.log { + "Covariance matrix:" + "\n" + NamedMatrix.toStringWithSymbols(covar, this) + } + return covar.named(symbols) } override suspend fun optimize(problem: XYFit): XYFit { val qowRuns = problem.getFeature()?.runs ?: 2 + val iterations = problem.getFeature()?.maxIterations ?: 50 + val freeParameters: Map = problem.getFeature()?.let { op -> + problem.startPoint.filterKeys { it in op.symbols } + } ?: problem.startPoint - var qow = QoWeight(problem, problem.startPoint) - var res = qow.newtonianRun() + var qow = QoWeight(problem, freeParameters) + var res = qow.newtonianRun(maxSteps = iterations) repeat(qowRuns - 1) { - qow = QoWeight(problem, res.parameters) - res = qow.newtonianRun() + qow = QoWeight(problem, res.freeParameters) + res = qow.newtonianRun(maxSteps = iterations) } - return res.problem.withFeature(OptimizationResult(res.parameters)) + val covariance = res.covariance() + return res.problem.withFeature(OptimizationResult(res.freeParameters), OptimizationCovariance(covariance)) } } \ No newline at end of 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 bba7a7113..5c28826ee 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 @@ -152,7 +152,7 @@ public suspend fun XYColumnarData.fitWith( */ public val XYFit.chiSquaredOrNull: Double? get() { - val result = resultPointOrNull ?: return null + val result = startPoint + (resultPointOrNull ?: return null) return data.indices.sumOf { index -> @@ -164,4 +164,7 @@ public val XYFit.chiSquaredOrNull: Double? ((y - mu) / yErr).pow(2) } - } \ No newline at end of file + } + +public val XYFit.dof: Int + get() = data.size - (getFeature()?.symbols?.size ?: startPoint.size) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/chiSquaredExpression.kt similarity index 87% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/chiSquaredExpression.kt index 59dfeb8ea..ca9755ad5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/chiSquaredExpression.kt @@ -1,10 +1,13 @@ /* - * Copyright 2018-2022 KMath contributors. + * Copyright 2018-2023 KMath 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 +package space.kscience.kmath.stat +import space.kscience.kmath.expressions.AutoDiffProcessor +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.ExpressionAlgebra import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.asIterable import space.kscience.kmath.structures.Buffer From d97888f1350250e07d8c186714d58e05484a06a5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 24 Jan 2023 21:22:25 +0300 Subject: [PATCH 26/72] Fix test --- .../space/kscience/kmath/commons/optimization/OptimizeTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8b4631fca..03b1426f5 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 @@ -11,13 +11,13 @@ import space.kscience.kmath.expressions.DSFieldExpression import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.y import space.kscience.kmath.expressions.autodiff -import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.optimization.* import space.kscience.kmath.random.RandomGenerator +import space.kscience.kmath.stat.chiSquaredExpression import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import kotlin.test.Test From db3091354225a8a054de7acc281216ef7f569d04 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 3 Feb 2023 19:32:53 +0300 Subject: [PATCH 27/72] Move to build tools 0.14 --- benchmarks/build.gradle.kts | 7 +- .../kmath/benchmarks/IntegrationBenchmark.kt | 40 +++++++++ build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 2 +- .../kscience/kmath/functions/integrate.kt | 13 +++ .../kmath/functions/matrixIntegration.kt | 32 ++++--- .../kscience/kmath/linear/dotPerformance.kt | 6 +- .../space/kscience/kmath/series/analyzeDif.kt | 2 +- gradle.properties | 2 +- kmath-ast/build.gradle.kts | 89 +++++++++---------- .../commons/expressions/CmDsExpression.kt | 2 + kmath-complex/build.gradle.kts | 10 +-- .../space/kscience/kmath/complex/Complex.kt | 2 + kmath-core/build.gradle.kts | 4 +- .../kscience/kmath/expressions/NamedMatrix.kt | 2 + .../kmath/operations/algebraExtensions.kt | 11 +++ kmath-coroutines/build.gradle.kts | 25 ++---- .../kmath/coroutines/coroutinesExtra.kt | 2 + .../kscience/kmath/streaming/BufferFlow.kt | 3 + kmath-dimensions/build.gradle.kts | 24 +++-- kmath-for-real/build.gradle.kts | 6 +- kmath-functions/build.gradle.kts | 2 + kmath-geometry/build.gradle.kts | 6 +- kmath-histograms/build.gradle.kts | 2 + kmath-jupyter/build.gradle.kts | 5 +- kmath-memory/build.gradle.kts | 2 + kmath-multik/build.gradle.kts | 5 ++ kmath-optimization/build.gradle.kts | 2 + kmath-stat/build.gradle.kts | 4 +- kmath-tensors/build.gradle.kts | 3 + kmath-trajectory/build.gradle.kts | 6 +- test-utils/build.gradle.kts | 2 + 32 files changed, 205 insertions(+), 120 deletions(-) create mode 100644 benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/IntegrationBenchmark.kt diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index ea2349d91..3a985cbb4 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -50,8 +50,6 @@ kotlin { val jvmMain by getting { dependencies { - implementation("org.openjdk.jmh:jmh-core:1.36") - implementation("org.openjdk.jmh:jmh-generator-annprocess:1.36") implementation(project(":kmath-commons")) implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) @@ -144,6 +142,11 @@ benchmark { commonConfiguration() include("ViktorLogBenchmark") } + + configurations.register("integration") { + commonConfiguration() + include("IntegrationBenchmark") + } } kotlin.sourceSets.all { diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/IntegrationBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/IntegrationBenchmark.kt new file mode 100644 index 000000000..6cc649fe9 --- /dev/null +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/IntegrationBenchmark.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2018-2023 KMath 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.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import org.openjdk.jmh.infra.Blackhole +import space.kscience.kmath.complex.Complex +import space.kscience.kmath.complex.algebra +import space.kscience.kmath.integration.gaussIntegrator +import space.kscience.kmath.integration.integrate +import space.kscience.kmath.integration.value +import space.kscience.kmath.operations.algebra + + +@State(Scope.Benchmark) +internal class IntegrationBenchmark { + + @Benchmark + fun doubleIntegration(blackhole: Blackhole) { + val res = Double.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double -> + //sin(1 / x) + 1/x + }.value + blackhole.consume(res) + } + + @Benchmark + fun complexIntegration(blackhole: Blackhole) = with(Complex.algebra) { + val res = gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double -> +// sin(1 / x) + i * cos(1 / x) + 1/x - i/x + }.value + blackhole.consume(res) + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 8731dbc70..9b1101a22 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-9" + version = "0.3.1-dev-10" } subprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 67df0aab4..afa36ed1e 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -19,7 +19,7 @@ val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get() dependencies { api("space.kscience:gradle-tools:$toolsVersion") //plugins form benchmarks - api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion") + api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.7") //api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //to be used inside build-script only //implementation(spclibs.kotlinx.serialization.json) 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 28169f15a..e8534d002 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -5,6 +5,11 @@ package space.kscience.kmath.functions +import space.kscience.kmath.complex.Complex +import space.kscience.kmath.complex.ComplexField +import space.kscience.kmath.complex.ComplexField.div +import space.kscience.kmath.complex.ComplexField.minus +import space.kscience.kmath.complex.algebra import space.kscience.kmath.integration.gaussIntegrator import space.kscience.kmath.integration.integrate import space.kscience.kmath.integration.value @@ -20,4 +25,12 @@ fun main() { //the value is nullable because in some cases the integration could not succeed println(result.value) + + + repeat(100000) { + Complex.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double -> +// sin(1 / x) + i * cos(1 / x) + 1 / x - ComplexField.i / x + }.value + } } \ No newline at end of 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 1b578626d..baba2eb28 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -12,23 +12,21 @@ import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.structureND import space.kscience.kmath.nd.withNdAlgebra import space.kscience.kmath.operations.algebra -import space.kscience.kmath.operations.invoke +import kotlin.math.pow -fun main(): Unit = Double.algebra { - withNdAlgebra(2, 2) { +fun main(): Unit = Double.algebra.withNdAlgebra(2, 2) { - //Produce a diagonal StructureND - fun diagonal(v: Double) = structureND { (i, j) -> - if (i == j) v else 0.0 - } - - //Define a function in a nd space - val function: (Double) -> StructureND = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 } - - //get the result of the integration - val result = gaussIntegrator.integrate(0.0..10.0, function = function) - - //the value is nullable because in some cases the integration could not succeed - println(result.value) + //Produce a diagonal StructureND + fun diagonal(v: Double) = structureND { (i, j) -> + if (i == j) v else 0.0 } -} \ No newline at end of file + + //Define a function in a nd space + val function: (Double) -> StructureND = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 } + + //get the result of the integration + val result = gaussIntegrator.integrate(0.0..10.0, function = function) + + //the value is nullable because in some cases the integration could not succeed + println(result.value) +} 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 d9c3281f2..79eddc6c3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt @@ -7,8 +7,10 @@ package space.kscience.kmath.linear import space.kscience.kmath.operations.algebra import kotlin.random.Random -import kotlin.system.measureTimeMillis +import kotlin.time.ExperimentalTime +import kotlin.time.measureTime +@OptIn(ExperimentalTime::class) fun main() { val random = Random(12224) val dim = 1000 @@ -21,7 +23,7 @@ fun main() { if (i <= j) random.nextDouble() else 0.0 } - val time = measureTimeMillis { + val time = measureTime { with(Double.algebra.linearSpace) { repeat(10) { matrix1 dot matrix2 diff --git a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt index c1b0c056e..c94cb0e71 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -37,7 +37,7 @@ fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 val s4 = DoubleBufferOps.ln(s3) - val kmTest: KMComparisonResult = ksComparisonStatistic(s1, s2) + @Suppress("UNUSED_VARIABLE") val kmTest: KMComparisonResult = ksComparisonStatistic(s1, s2) Plotly.page { h1 { +"This is my plot" } diff --git a/gradle.properties b/gradle.properties index 3016246b2..16cdd3551 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.13.4-kotlin-1.8.0 +toolsVersion=0.14.0-kotlin-1.8.10 org.gradle.parallel=true diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 7fd0f43f7..c60977862 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -3,65 +3,58 @@ plugins { } kscience{ + jvm() + js() native() + + dependencies { + api(projects.kmathCore) + api("com.github.h0tk3y.betterParse:better-parse:0.4.4") + } + + testDependencies { + implementation(projects.kmathComplex) + } + + dependencies(jsMain) { + implementation(npm("astring", "1.7.5")) + implementation(npm("binaryen", "101.0.0")) + implementation(npm("js-base64", "3.6.1")) + } + + dependencies(jvmMain){ + implementation("org.ow2.asm:asm-commons:9.2") + } + } -kotlin.js { - nodejs { - testTask { - useMocha().timeout = "0" +kotlin { + js { + nodejs { + testTask { + useMocha().timeout = "0" + } + } + + browser { + testTask { + useMocha().timeout = "0" + } } } - browser { - testTask { - useMocha().timeout = "0" - } + sourceSets { + filter { it.name.contains("test", true) } + .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) + .forEach { it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } } } -kotlin.sourceSets { - filter { it.name.contains("test", true) } - .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) - .forEach { it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } - - commonMain { - dependencies { - api("com.github.h0tk3y.betterParse:better-parse:0.4.4") - api(project(":kmath-core")) - } - } - - commonTest { - dependencies { - implementation(project(":kmath-complex")) - } - } - - jsMain { - dependencies { - implementation(npm("astring", "1.7.5")) - implementation(npm("binaryen", "101.0.0")) - implementation(npm("js-base64", "3.6.1")) - } - } - - jvmMain { - dependencies { - implementation("org.ow2.asm:asm-commons:9.2") - } - } -} - -//Workaround for https://github.com/Kotlin/dokka/issues/1455 -tasks.dokkaHtml { - dependsOn(tasks.build) -} - -if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1") - tasks.jvmTest { +if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1") { + tasks.withType { jvmArgs("-Dspace.kscience.kmath.ast.dump.generated.classes=1") } +} readme { maturity = space.kscience.gradle.Maturity.EXPERIMENTAL diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/CmDsExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/CmDsExpression.kt index f2af49087..cb7fb543f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/CmDsExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/CmDsExpression.kt @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("DEPRECATION") + package space.kscience.kmath.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index b63def0a7..76d5a4c9a 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -3,14 +3,12 @@ plugins { } kscience { + jvm() + js() native() -} -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-core")) - } + dependencies { + api(projects.kmathCore) } } 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 7bf8af4e8..bb580989b 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 @@ -80,6 +80,8 @@ public object ComplexField : override fun add(left: Complex, right: Complex): Complex = Complex(left.re + right.re, left.im + right.im) // override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble()) +// override fun Complex.minus(arg: Complex): Complex = Complex(re - arg.re, im - arg.im) + override fun multiply(left: Complex, right: Complex): Complex = Complex(left.re * right.re - left.im * right.im, left.re * right.im + left.im * right.re) diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index f33d33324..0e4646bed 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -3,10 +3,12 @@ plugins { } kscience{ + jvm() + js() native() dependencies { - api(project(":kmath-memory")) + api(projects.kmathMemory) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt index f0b27ffa2..24bdfce7e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/NamedMatrix.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.expressions import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.getOrNull @@ -16,6 +17,7 @@ public class NamedMatrix(public val values: Matrix, public val indexer: Sy public companion object { + @OptIn(PerformancePitfall::class) public fun toStringWithSymbols(values: Matrix<*>, indexer: SymbolIndexer): String = buildString { appendLine(indexer.symbols.joinToString(separator = "\t", prefix = "\t\t")) indexer.symbols.forEach { i -> 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 f05ddafb8..84fb2ea41 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 @@ -92,6 +92,17 @@ public fun > Group.abs(value: T): T = if (value > zero) val */ public fun Iterable.sumWith(group: Group): T = group.sum(this) +/** + * Sum extracted elements of [Iterable] with given [group] + * + * @receiver the collection to sum up. + * @param group tha algebra that provides addition + * @param extractor the (inline) lambda function to extract value + */ +public inline fun Iterable.sumWithGroupOf(group: Group, extractor: (T) -> R): R = this.fold(group.zero) { left: R, right: T -> + group.add(left, extractor(right)) +} + /** * Returns the sum of all elements in the sequence in provided space. * diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 529084619..9d5cfabe4 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -2,25 +2,14 @@ plugins { id("space.kscience.gradle.mpp") } -kscience{ +kscience { + jvm() + js() native() -} - -kotlin.sourceSets { - all { - with(languageSettings) { - optIn("kotlinx.coroutines.InternalCoroutinesApi") - optIn("kotlinx.coroutines.ExperimentalCoroutinesApi") - optIn("kotlinx.coroutines.FlowPreview") - } - } - - commonMain { - dependencies { - api(project(":kmath-core")) - api(project(":kmath-complex")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${space.kscience.gradle.KScienceVersions.coroutinesVersion}") - } + dependencies { + api(project(":kmath-core")) + api(project(":kmath-complex")) + api(spclibs.kotlinx.coroutines.core) } } 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 7bae388a8..2fd4f0057 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 @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class) + package space.kscience.kmath.coroutines import kotlinx.coroutines.* 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 8aa5a937c..ccd329064 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 @@ -3,8 +3,11 @@ * 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(FlowPreview::class) + package space.kscience.kmath.streaming +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.flatMapConcat diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 29c0eccb6..be1fc65a0 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -3,25 +3,21 @@ plugins { } kscience{ + jvm() + js() native() + + dependencies{ + api(projects.kmathCore) + } + + dependencies(jvmMain) { + api(kotlin("reflect")) + } } description = "A proof of concept module for adding type-safe dimensions to structures" -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-core")) - } - } - - jvmMain { - dependencies { - api(kotlin("reflect")) - } - } -} - readme { maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 1e964d99c..99ce5903f 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -3,11 +3,15 @@ plugins { } kscience { + jvm() + js() native() + dependencies { api(projects.kmathCore) } - dependencies("commonTest") { + + testDependencies { implementation(projects.testUtils) } } diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 9c2cd8352..08e76aef0 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience{ + jvm() + js() native() } diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 52d76d5d2..f248a1717 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -3,8 +3,12 @@ plugins { } kscience{ + jvm() + js() native() - withContextReceivers() + + useContextReceivers() + useSerialization() dependencies{ api(projects.kmath.kmathComplex) } diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 9d7ac33e4..33704c29e 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience{ + jvm() + js() native() } diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index d92b6ca0d..a600261b3 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -4,15 +4,12 @@ plugins { } dependencies { + api(spclibs.kotlinx.html) api(project(":kmath-ast")) api(project(":kmath-complex")) api(project(":kmath-for-real")) } -kscience { - useHtml() -} - readme { maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 50eb448a7..4f0f996b9 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience { + jvm() + js() native() } diff --git a/kmath-multik/build.gradle.kts b/kmath-multik/build.gradle.kts index 39c03ab9b..fc51d2c21 100644 --- a/kmath-multik/build.gradle.kts +++ b/kmath-multik/build.gradle.kts @@ -6,6 +6,11 @@ description = "JetBrains Multik connector" val multikVersion: String by rootProject.extra +kscience { + jvm() + js() +} + kotlin{ sourceSets{ commonMain{ diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index ba49d49bf..0a8e47728 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience{ + jvm() + js() native() } diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index bc98129a9..267bfd0f3 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience{ + jvm() + js() native() } @@ -14,7 +16,7 @@ kotlin.sourceSets { } } - jvmMain { + getByName("jvmMain") { dependencies { api("org.apache.commons:commons-rng-sampling:1.3") api("org.apache.commons:commons-rng-simple:1.3") diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 1060b37b4..d27faeeef 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -3,7 +3,10 @@ plugins { } kscience{ + jvm() + js() native() + dependencies { api(projects.kmathCore) api(projects.kmathStat) diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts index 16a84b691..689c3265b 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -3,8 +3,12 @@ plugins { } kscience{ + jvm() + js() native() - withContextReceivers() + + useContextReceivers() + useSerialization() dependencies { api(projects.kmath.kmathGeometry) } diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts index 98bd7328d..b860a62ec 100644 --- a/test-utils/build.gradle.kts +++ b/test-utils/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } kscience{ + jvm() + js() native() } From 0366a69123fc45690d5b6983d83a3c90929d1084 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 3 Feb 2023 19:33:22 +0300 Subject: [PATCH 28/72] Refactor trajectory --- .../space/kscience/kmath/geometry/Circle2D.kt | 4 +- .../kmath/geometry/Euclidean2DSpace.kt | 21 +++ .../kmath/geometry/Euclidean3DSpace.kt | 22 +++ .../space/kscience/kmath/geometry/Line.kt | 11 ++ .../kscience/kmath/trajectory/DubinsPath.kt | 173 ++++++++++-------- .../kscience/kmath/trajectory/DubinsPose2D.kt | 41 ++++- .../kscience/kmath/trajectory/Trajectory2D.kt | 13 +- .../space/kscience/kmath/trajectory/route.kt | 16 -- .../kmath/trajectory/dubins/DubinsTests.kt | 34 ++-- 9 files changed, 217 insertions(+), 118 deletions(-) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt 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 index 162130908..8beef6fee 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -5,13 +5,15 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.Serializable import kotlin.math.PI /** * A circle in 2D space */ +@Serializable public data class Circle2D( - public val center: DoubleVector2D, + @Serializable(Euclidean2DSpace.VectorSerializer::class) public val center: DoubleVector2D, public val radius: Double ) 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 a8310503c..3df8dba7b 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 @@ -5,6 +5,12 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import space.kscience.kmath.linear.Point import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations @@ -33,6 +39,7 @@ public operator fun Vector2D.component1(): T = x public operator fun Vector2D.component2(): T = y public typealias DoubleVector2D = Vector2D +public typealias Float64Vector2D = Vector2D public val Vector2D.r: Double get() = Euclidean2DSpace.norm(this) @@ -44,11 +51,25 @@ public object Euclidean2DSpace : GeometrySpace, ScaleOperations, Norm { + @Serializable + @SerialName("Float64Vector2D") private data class Vector2DImpl( override val x: Double, override val y: Double, ) : DoubleVector2D + public object VectorSerializer : KSerializer { + private val proxySerializer = Vector2DImpl.serializer() + override val descriptor: SerialDescriptor get() = proxySerializer.descriptor + + override fun deserialize(decoder: Decoder): DoubleVector2D = decoder.decodeSerializableValue(proxySerializer) + + override fun serialize(encoder: Encoder, value: DoubleVector2D) { + val vector = value as? Vector2DImpl ?: Vector2DImpl(value.x, value.y) + encoder.encodeSerializableValue(proxySerializer, vector) + } + } + public fun vector(x: Number, y: Number): DoubleVector2D = Vector2DImpl(x.toDouble(), y.toDouble()) override val zero: DoubleVector2D by lazy { vector(0.0, 0.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 d214e4edf..cc641a3f1 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 @@ -5,6 +5,12 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import space.kscience.kmath.linear.Point import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations @@ -45,17 +51,33 @@ public fun Buffer.asVector3D(): Vector3D = object : Vector3D { } public typealias DoubleVector3D = Vector3D +public typealias Float64Vector3D = Vector3D public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this) public object Euclidean3DSpace : GeometrySpace, ScaleOperations, Norm { + + @Serializable + @SerialName("Float64Vector3D") private data class Vector3DImpl( override val x: Double, override val y: Double, override val z: Double, ) : DoubleVector3D + public object VectorSerializer : KSerializer { + private val proxySerializer = Vector3DImpl.serializer() + override val descriptor: SerialDescriptor get() = proxySerializer.descriptor + + override fun deserialize(decoder: Decoder): DoubleVector3D = decoder.decodeSerializableValue(proxySerializer) + + override fun serialize(encoder: Encoder, value: DoubleVector3D) { + val vector = value as? Vector3DImpl ?: Vector3DImpl(value.x, value.y, value.z) + encoder.encodeSerializableValue(proxySerializer, vector) + } + } + public fun vector(x: Number, y: Number, z: Number): DoubleVector3D = Vector3DImpl(x.toDouble(), y.toDouble(), z.toDouble()) 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 bf14d6d4a..ab322ddca 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 @@ -5,10 +5,13 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.Serializable + /** * 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 */ +@Serializable public data class Line(val base: V, val direction: V) public typealias Line2D = Line @@ -17,4 +20,12 @@ public typealias Line3D = Line /** * A directed line segment between [begin] and [end] */ +@Serializable public data class LineSegment(val begin: V, val end: V) + +public fun LineSegment.line(algebra: GeometrySpace): Line = with(algebra) { + Line(begin, end - begin) +} + +public typealias LineSegment2D = LineSegment +public typealias LineSegment3D = LineSegment 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 index 1ba9936ee..6bbf3e55b 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -57,7 +57,11 @@ internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightTraj internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory2D? = innerTangent(base, direction, CircleTrajectory2D.Direction.RIGHT) -private fun innerTangent(base: Circle2D, direction: Circle2D, side: CircleTrajectory2D.Direction): StraightTrajectory2D? = +private fun innerTangent( + base: Circle2D, + direction: Circle2D, + side: CircleTrajectory2D.Direction, +): StraightTrajectory2D? = with(Euclidean2DSpace) { val centers = StraightTrajectory2D(base.center, direction.center) if (centers.length < base.radius * 2) return null @@ -76,43 +80,49 @@ private fun innerTangent(base: Circle2D, direction: Circle2D, side: CircleTrajec internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) + @Suppress("DuplicatedCode") -public class DubinsPath( - public val a: CircleTrajectory2D, - public val b: Trajectory2D, - public val c: CircleTrajectory2D, -) : CompositeTrajectory2D(listOf(a, b, c)) { +public object DubinsPath { - public val type: TYPE = TYPE.valueOf( - arrayOf( - a.direction.name[0], - if (b is CircleTrajectory2D) b.direction.name[0] else 'S', - c.direction.name[0] - ).toCharArray().concatToString() - ) - - public enum class TYPE { + public enum class Type { RLR, LRL, RSR, LSL, RSL, LSR } - public companion object { - public fun all( - start: DubinsPose2D, - end: DubinsPose2D, - 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) + /** + * Return Dubins trajectory type or null if trajectory is not a Dubins path + */ + public fun trajectoryTypeOf(trajectory2D: CompositeTrajectory2D): Type?{ + if(trajectory2D.segments.size != 3) return null + val a = trajectory2D.segments.first() as? CircleTrajectory2D ?: return null + val b = trajectory2D.segments[1] + val c = trajectory2D.segments.last() as? CircleTrajectory2D ?: return null + return Type.valueOf( + arrayOf( + a.direction.name[0], + if (b is CircleTrajectory2D) b.direction.name[0] else 'S', + c.direction.name[0] + ).toCharArray().concatToString() ) + } - public fun shortest(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath = - all(start, end, turningRadius).minBy { it.length } + public fun all( + start: DubinsPose2D, + end: DubinsPose2D, + 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 rlr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { + public fun shortest(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D = + all(start, end, turningRadius).minBy { it.length } + + public fun rlr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? = + with(Euclidean2DSpace) { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val centers = StraightTrajectory2D(c1.center, c2.center) @@ -132,7 +142,7 @@ public class DubinsPath( val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) - DubinsPath(a1, a2, a3) + CompositeTrajectory2D(a1, a2, a3) } val secondVariant = run { @@ -149,13 +159,14 @@ public class DubinsPath( val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) - DubinsPath(a1, a2, a3) + CompositeTrajectory2D(a1, a2, a3) } return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } - public fun lrl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath? = with(Euclidean2DSpace) { + public fun lrl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? = + with(Euclidean2DSpace) { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val centers = StraightTrajectory2D(c1.center, c2.center) @@ -175,10 +186,10 @@ public class DubinsPath( val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) - DubinsPath(a1, a2, a3) + CompositeTrajectory2D(a1, a2, a3) } - val secondVariant = run{ + val secondVariant = run { var theta = theta(centers.bearing - acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) @@ -192,50 +203,60 @@ public class DubinsPath( val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) - DubinsPath(a1, a2, a3) + CompositeTrajectory2D(a1, a2, a3) } return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant } - public fun rsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val s = leftOuterTangent(c1, c2) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) - return DubinsPath(a1, s, a3) - } - - public fun lsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): DubinsPath { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val s = rightOuterTangent(c1, c2) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) - return DubinsPath(a1, s, a3) - } - - public fun rsl(start: DubinsPose2D, end: DubinsPose2D, 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 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) - return DubinsPath(a1, s, a3) - } - - public fun lsr(start: DubinsPose2D, end: DubinsPose2D, 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 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) - return DubinsPath(a1, s, a3) - } + public fun rsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftOuterTangent(c1, c2) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) + return CompositeTrajectory2D(a1, s, a3) } -} \ No newline at end of file + + public fun lsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightOuterTangent(c1, c2) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) + return CompositeTrajectory2D(a1, s, a3) + } + + public fun rsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { + 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 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) + return CompositeTrajectory2D(a1, s, a3) + } + + public fun lsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { + 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 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) + return CompositeTrajectory2D(a1, s, a3) + } +} + +public fun interface MaxCurvature { + public fun compute(startPoint: PhaseVector2D): Double +} + +public fun DubinsPath.shortest( + start: PhaseVector2D, + end: PhaseVector2D, + maxCurvature: MaxCurvature, +): CompositeTrajectory2D = shortest(start, end, maxCurvature.compute(start)) + diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt index 5aa8c1455..ff2198bbb 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt @@ -2,35 +2,62 @@ * Copyright 2018-2022 KMath 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:UseSerializers(Euclidean2DSpace.VectorSerializer::class) package space.kscience.kmath.trajectory +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import space.kscience.kmath.geometry.DoubleVector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.Vector import kotlin.math.atan2 /** * Combination of [Vector] and its view angle (clockwise from positive y-axis direction) */ +@Serializable(DubinsPose2DSerializer::class) public interface DubinsPose2D : DoubleVector2D { - public val coordinate: DoubleVector2D + public val coordinates: DoubleVector2D public val bearing: Double } +@Serializable public class PhaseVector2D( - override val coordinate: DoubleVector2D, + override val coordinates: DoubleVector2D, public val velocity: DoubleVector2D, -) : DubinsPose2D, DoubleVector2D by coordinate { +) : DubinsPose2D, DoubleVector2D by coordinates { override val bearing: Double get() = atan2(velocity.x, velocity.y) } +@Serializable +@SerialName("DubinsPose2D") private class DubinsPose2DImpl( - override val coordinate: DoubleVector2D, + override val coordinates: DoubleVector2D, override val bearing: Double, -) : DubinsPose2D, DoubleVector2D by coordinate{ +) : DubinsPose2D, DoubleVector2D by coordinates{ - override fun toString(): String = "Pose2D(x=$x, y=$y, bearing=$bearing)" + override fun toString(): String = "DubinsPose2D(x=$x, y=$y, bearing=$bearing)" } +public object DubinsPose2DSerializer: KSerializer{ + private val proxySerializer = DubinsPose2DImpl.serializer() + + override val descriptor: SerialDescriptor + get() = proxySerializer.descriptor + + override fun deserialize(decoder: Decoder): DubinsPose2D { + return decoder.decodeSerializableValue(proxySerializer) + } + + override fun serialize(encoder: Encoder, value: DubinsPose2D) { + val pose = value as? DubinsPose2DImpl ?: DubinsPose2DImpl(value.coordinates, value.bearing) + encoder.encodeSerializableValue(proxySerializer, pose) + } +} public fun DubinsPose2D(coordinate: DoubleVector2D, theta: Double): DubinsPose2D = DubinsPose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index ffa23a537..120bedf90 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -2,15 +2,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. */ - +@file:UseSerializers(Euclidean2DSpace.VectorSerializer::class) package space.kscience.kmath.trajectory +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.DoubleVector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import kotlin.math.PI import kotlin.math.atan2 +@Serializable public sealed interface Trajectory2D { public val length: Double } @@ -18,6 +22,7 @@ public sealed interface Trajectory2D { /** * Straight path segment. The order of start and end defines the direction */ +@Serializable public data class StraightTrajectory2D( public val start: DoubleVector2D, public val end: DoubleVector2D, @@ -30,6 +35,7 @@ public data class StraightTrajectory2D( /** * An arc segment */ +@Serializable public data class CircleTrajectory2D( public val circle: Circle2D, public val start: DubinsPose2D, @@ -102,7 +108,10 @@ public data class CircleTrajectory2D( } } -public open class CompositeTrajectory2D(public val segments: List) : Trajectory2D { +@Serializable +public class CompositeTrajectory2D(public val segments: List) : Trajectory2D { override val length: Double get() = segments.sumOf { it.length } } +public fun CompositeTrajectory2D(vararg segments: Trajectory2D): CompositeTrajectory2D = CompositeTrajectory2D(segments.toList()) + 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 deleted file mode 100644 index 56350835d..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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, - maxCurvature: MaxCurvature, -): DubinsPath = shortest(start, end, maxCurvature.compute(start)) 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 index 5bbf8c294..0e14ae736 100644 --- 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 @@ -28,31 +28,33 @@ class DubinsTests { 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 + 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 } + val path = dubins.find { p -> DubinsPath.trajectoryTypeOf(p) === 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)) + val a = path.segments[0] as CircleTrajectory2D + val b = path.segments[1] + val c = path.segments[2] as CircleTrajectory2D + + assertTrue(start.equalsFloat(a.start)) + assertTrue(end.equalsFloat(c.end)) // Not working, theta double precision inaccuracy - if (path.b is CircleTrajectory2D) { - val b = path.b as CircleTrajectory2D - assertTrue(path.a.end.equalsFloat(b.start)) - assertTrue(path.c.start.equalsFloat(b.end)) - } else if (path.b is StraightTrajectory2D) { - val b = path.b as StraightTrajectory2D - assertTrue(path.a.end.equalsFloat(DubinsPose2D(b.start, b.bearing))) - assertTrue(path.c.start.equalsFloat(DubinsPose2D(b.end, b.bearing))) + if (b is CircleTrajectory2D) { + assertTrue(a.end.equalsFloat(b.start)) + assertTrue(c.start.equalsFloat(b.end)) + } else if (b is StraightTrajectory2D) { + assertTrue(a.end.equalsFloat(DubinsPose2D(b.start, b.bearing))) + assertTrue(c.start.equalsFloat(DubinsPose2D(b.end, b.bearing))) } } } From 2c6d1e89c512627f79c579e7305197d3a3ae98db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 5 Feb 2023 20:05:53 +0300 Subject: [PATCH 29/72] Update type-safe angles --- CHANGELOG.md | 1 + .../space/kscience/kmath/geometry/angles.kt | 53 +++++++++++-------- .../kscience/kmath/geometry/AngleTest.kt | 16 ++++++ .../kscience/kmath/trajectory/DubinsPath.kt | 39 ++++++-------- .../kscience/kmath/trajectory/DubinsPose2D.kt | 12 ++--- .../kscience/kmath/trajectory/Trajectory2D.kt | 42 +++++++-------- .../space/kscience/kmath/trajectory/math.kt | 8 +-- .../kmath/trajectory/segments/ArcTests.kt | 6 +-- .../kmath/trajectory/segments/LineTests.kt | 12 ++--- 9 files changed, 104 insertions(+), 85 deletions(-) create mode 100644 kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/AngleTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index b8cb0d976..404366a03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed +- Trajectory use type-safe angles - Tensor operations switched to prefix notation - Row-wise and column-wise ND shapes in the core - Shape is read-only 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 index e7b0afcda..45022ad05 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt @@ -7,8 +7,9 @@ package space.kscience.kmath.geometry import kotlin.jvm.JvmInline import kotlin.math.PI +import kotlin.math.floor -public sealed interface Angle { +public sealed interface Angle : Comparable { public fun toRadians(): Radians public fun toDegrees(): Degrees @@ -17,7 +18,15 @@ public sealed interface Angle { public operator fun times(other: Number): Angle public operator fun div(other: Number): Angle + public operator fun div(other: Angle): Double public operator fun unaryMinus(): Angle + + public companion object { + public val zero: Radians = Radians(0.0) + public val pi: Radians = Radians(PI) + public val piTimes2: Radians = Radians(PI * 2) + public val piDiv2: Radians = Radians(PI / 2) + } } /** @@ -28,12 +37,16 @@ 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 plus(other: Angle): Radians = Radians(value + other.radians) + public override fun minus(other: Angle): Radians = Radians(value - other.radians) - public override fun times(other: Number): Radians = Radians(value + other.toDouble()) + public override fun times(other: Number): Radians = Radians(value * other.toDouble()) public override fun div(other: Number): Radians = Radians(value / other.toDouble()) + override fun div(other: Angle): Double = value / other.radians + public override fun unaryMinus(): Radians = Radians(-value) + + override fun compareTo(other: Angle): Int = value.compareTo(other.radians) } public fun sin(angle: Angle): Double = kotlin.math.sin(angle.toRadians().value) @@ -42,6 +55,8 @@ public fun tan(angle: Angle): Double = kotlin.math.tan(angle.toRadians().value) public val Number.radians: Radians get() = Radians(toDouble()) +public val Angle.radians: Double get() = toRadians().value + /** * Type safe degrees */ @@ -50,30 +65,26 @@ 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 plus(other: Angle): Degrees = Degrees(value + other.degrees) + public override fun minus(other: Angle): Degrees = Degrees(value - other.degrees) - public override fun times(other: Number): Degrees = Degrees(value + other.toDouble()) + public override fun times(other: Number): Degrees = Degrees(value * other.toDouble()) public override fun div(other: Number): Degrees = Degrees(value / other.toDouble()) + override fun div(other: Angle): Double = value / other.degrees + public override fun unaryMinus(): Degrees = Degrees(-value) + + override fun compareTo(other: Angle): Int = value.compareTo(other.degrees) } public val Number.degrees: Degrees get() = Degrees(toDouble()) +public val Angle.degrees: Double get() = toDegrees().value + /** - * A holder class for Pi representation in radians and degrees + * Normalized angle 2 PI range symmetric around [center]. By default, uses (0, 2PI) range. */ -public object Pi { - public val radians: Radians = Radians(PI) - public val degrees: Degrees = radians.toDegrees() -} +public fun Angle.normalized(center: Angle = Angle.pi): Angle = + this - Angle.piTimes2 * floor((radians + PI - center.radians) / PI / 2) -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 +public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/AngleTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/AngleTest.kt new file mode 100644 index 000000000..b8086eb75 --- /dev/null +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/AngleTest.kt @@ -0,0 +1,16 @@ +package space.kscience.kmath.geometry + +import kotlin.test.Test +import kotlin.test.assertEquals + +class AngleTest { + @Test + fun normalization() { + assertEquals(30.degrees, 390.degrees.normalized()) + assertEquals(30.degrees, (-330).degrees.normalized()) + assertEquals(200.degrees, 200.degrees.normalized()) + assertEquals(30.degrees, 390.degrees.normalized(Angle.zero)) + assertEquals(30.degrees, (-330).degrees.normalized(Angle.zero)) + assertEquals((-160).degrees, 200.degrees.normalized(Angle.zero)) + } +} \ No newline at end of file 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 index 6bbf3e55b..568ef691a 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -5,13 +5,9 @@ package space.kscience.kmath.trajectory -import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.* 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 DubinsPose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first @@ -65,12 +61,11 @@ private fun innerTangent( with(Euclidean2DSpace) { val centers = StraightTrajectory2D(base.center, direction.center) if (centers.length < base.radius * 2) return null - val angle = theta( - when (side) { - CircleTrajectory2D.Direction.LEFT -> centers.bearing + acos(base.radius * 2 / centers.length) - CircleTrajectory2D.Direction.RIGHT -> centers.bearing - acos(base.radius * 2 / centers.length) - } - ) + val angle = when (side) { + CircleTrajectory2D.Direction.LEFT -> centers.bearing + acos(base.radius * 2 / centers.length).radians + CircleTrajectory2D.Direction.RIGHT -> centers.bearing - acos(base.radius * 2 / centers.length).radians + }.normalized() + val dX = base.radius * sin(angle) val dY = base.radius * cos(angle) val p1 = vector(base.center.x + dX, base.center.y + dY) @@ -78,8 +73,6 @@ private fun innerTangent( return StraightTrajectory2D(p1, p2) } -internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) - @Suppress("DuplicatedCode") public object DubinsPath { @@ -91,8 +84,8 @@ public object DubinsPath { /** * Return Dubins trajectory type or null if trajectory is not a Dubins path */ - public fun trajectoryTypeOf(trajectory2D: CompositeTrajectory2D): Type?{ - if(trajectory2D.segments.size != 3) return null + public fun trajectoryTypeOf(trajectory2D: CompositeTrajectory2D): Type? { + if (trajectory2D.segments.size != 3) return null val a = trajectory2D.segments.first() as? CircleTrajectory2D ?: return null val b = trajectory2D.segments[1] val c = trajectory2D.segments.last() as? CircleTrajectory2D ?: return null @@ -129,13 +122,13 @@ public object DubinsPath { if (centers.length > turningRadius * 4) return null val firstVariant = run { - var theta = theta(centers.bearing - acos(centers.length / (turningRadius * 4))) + var theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() 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.bearing + acos(centers.length / (turningRadius * 4))) + theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) @@ -146,13 +139,13 @@ public object DubinsPath { } val secondVariant = run { - var theta = theta(centers.bearing + acos(centers.length / (turningRadius * 4))) + var theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() 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.bearing - acos(centers.length / (turningRadius * 4))) + theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) @@ -173,13 +166,13 @@ public object DubinsPath { if (centers.length > turningRadius * 4) return null val firstVariant = run { - var theta = theta(centers.bearing + acos(centers.length / (turningRadius * 4))) + var theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() 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.bearing - acos(centers.length / (turningRadius * 4))) + theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) @@ -190,13 +183,13 @@ public object DubinsPath { } val secondVariant = run { - var theta = theta(centers.bearing - acos(centers.length / (turningRadius * 4))) + var theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() 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.bearing + acos(centers.length / (turningRadius * 4))) + theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt index ff2198bbb..8362d0cb5 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt @@ -12,9 +12,7 @@ import kotlinx.serialization.UseSerializers import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import space.kscience.kmath.geometry.DoubleVector2D -import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.Vector +import space.kscience.kmath.geometry.* import kotlin.math.atan2 /** @@ -23,7 +21,7 @@ import kotlin.math.atan2 @Serializable(DubinsPose2DSerializer::class) public interface DubinsPose2D : DoubleVector2D { public val coordinates: DoubleVector2D - public val bearing: Double + public val bearing: Angle } @Serializable @@ -31,14 +29,14 @@ public class PhaseVector2D( override val coordinates: DoubleVector2D, public val velocity: DoubleVector2D, ) : DubinsPose2D, DoubleVector2D by coordinates { - override val bearing: Double get() = atan2(velocity.x, velocity.y) + override val bearing: Angle get() = atan2(velocity.x, velocity.y).radians } @Serializable @SerialName("DubinsPose2D") private class DubinsPose2DImpl( override val coordinates: DoubleVector2D, - override val bearing: Double, + override val bearing: Angle, ) : DubinsPose2D, DoubleVector2D by coordinates{ override fun toString(): String = "DubinsPose2D(x=$x, y=$y, bearing=$bearing)" @@ -60,4 +58,4 @@ public object DubinsPose2DSerializer: KSerializer{ } } -public fun DubinsPose2D(coordinate: DoubleVector2D, theta: Double): DubinsPose2D = DubinsPose2DImpl(coordinate, theta) \ No newline at end of file +public fun DubinsPose2D(coordinate: DoubleVector2D, theta: Angle): DubinsPose2D = DubinsPose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 120bedf90..b8916e748 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -3,15 +3,13 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:UseSerializers(Euclidean2DSpace.VectorSerializer::class) + package space.kscience.kmath.trajectory import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.DoubleVector2D -import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.* import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import kotlin.math.PI import kotlin.math.atan2 @Serializable @@ -29,7 +27,7 @@ public data class StraightTrajectory2D( ) : Trajectory2D { override val length: Double get() = start.distanceTo(end) - public val bearing: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) + public val bearing: Angle get() = (atan2(end.x - start.x, end.y - start.y).radians).normalized() } /** @@ -49,26 +47,25 @@ public data class CircleTrajectory2D( /** * Arc length in radians */ - val arcLength: Double - get() = theta( - if (direction == Direction.LEFT) { - start.bearing - end.bearing - } else { - end.bearing - start.bearing - } - ) + val arcLength: Angle + get() = if (direction == Direction.LEFT) { + start.bearing - end.bearing + } else { + end.bearing - start.bearing + }.normalized() + override val length: Double by lazy { - circle.radius * arcLength + circle.radius * arcLength.radians } public val direction: Direction by lazy { if (start.y < circle.center.y) { - if (start.bearing > PI) Direction.RIGHT else Direction.LEFT + if (start.bearing > Angle.pi) Direction.RIGHT else Direction.LEFT } else if (start.y > circle.center.y) { - if (start.bearing < PI) Direction.RIGHT else Direction.LEFT + if (start.bearing < Angle.pi) Direction.RIGHT else Direction.LEFT } else { - if (start.bearing == 0.0) { + if (start.bearing == Angle.zero) { if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT } else { if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT @@ -85,13 +82,13 @@ public data class CircleTrajectory2D( ): CircleTrajectory2D { fun calculatePose( vector: DoubleVector2D, - theta: Double, + theta: Angle, direction: Direction, ): DubinsPose2D = DubinsPose2D( vector, when (direction) { - Direction.LEFT -> theta(theta - PI / 2) - Direction.RIGHT -> theta(theta + PI / 2) + Direction.LEFT -> (theta - Angle.piDiv2).normalized() + Direction.RIGHT -> (theta + Angle.piDiv2).normalized() } ) @@ -100,7 +97,7 @@ public data class CircleTrajectory2D( val pose1 = calculatePose(start, s1.bearing, direction) val pose2 = calculatePose(end, s2.bearing, direction) val trajectory = CircleTrajectory2D(Circle2D(center, s1.length), pose1, pose2) - if(trajectory.direction != direction){ + if (trajectory.direction != direction) { error("Trajectory direction mismatch") } return trajectory @@ -113,5 +110,6 @@ public class CompositeTrajectory2D(public val segments: List) : Tr override val length: Double get() = segments.sumOf { it.length } } -public fun CompositeTrajectory2D(vararg segments: Trajectory2D): CompositeTrajectory2D = CompositeTrajectory2D(segments.toList()) +public fun CompositeTrajectory2D(vararg segments: Trajectory2D): CompositeTrajectory2D = + CompositeTrajectory2D(segments.toList()) 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 index 4599f30f8..c69ad24f1 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt @@ -6,19 +6,21 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.radians +import space.kscience.kmath.geometry.sin 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 DubinsPose2D.equalsFloat(other: DubinsPose2D) = x.equalFloat(other.x) && y.equalFloat(other.y) && bearing.equalFloat(other.bearing) +fun DubinsPose2D.equalsFloat(other: DubinsPose2D) = + x.equalFloat(other.x) && y.equalFloat(other.y) && bearing.radians.equalFloat(other.bearing.radians) fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, start) -fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace){ +fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace) { val dX = width * sin(inverse().bearing) val dY = width * sin(bearing) 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 index af1444ade..643f9eaaa 100644 --- 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 @@ -8,8 +8,8 @@ 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.geometry.degrees import space.kscience.kmath.trajectory.CircleTrajectory2D -import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.test.Test import kotlin.test.assertEquals @@ -20,7 +20,7 @@ class ArcTests { val circle = Circle2D(vector(0.0, 0.0), 2.0) val arc = CircleTrajectory2D.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), CircleTrajectory2D.Direction.RIGHT) assertEquals(circle.circumference / 4, arc.length, 1.0) - assertEquals(0.0, arc.start.bearing.radiansToDegrees()) - assertEquals(90.0, arc.end.bearing.radiansToDegrees()) + assertEquals(0.0, arc.start.bearing.degrees) + assertEquals(90.0, arc.end.bearing.degrees) } } 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 index 03320a3df..54deb2193 100644 --- 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.degrees import space.kscience.kmath.trajectory.StraightTrajectory2D -import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow import kotlin.math.sqrt import kotlin.test.Test @@ -19,19 +19,19 @@ class LineTests { fun lineTest() = with(Euclidean2DSpace){ val straight = StraightTrajectory2D(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.bearing.radiansToDegrees()) + assertEquals(45.0, straight.bearing.degrees) } @Test fun lineAngleTest() = with(Euclidean2DSpace){ //val zero = Vector2D(0.0, 0.0) val north = StraightTrajectory2D(zero, vector(0.0, 2.0)) - assertEquals(0.0, north.bearing.radiansToDegrees()) + assertEquals(0.0, north.bearing.degrees) val east = StraightTrajectory2D(zero, vector(2.0, 0.0)) - assertEquals(90.0, east.bearing.radiansToDegrees()) + assertEquals(90.0, east.bearing.degrees) val south = StraightTrajectory2D(zero, vector(0.0, -2.0)) - assertEquals(180.0, south.bearing.radiansToDegrees()) + assertEquals(180.0, south.bearing.degrees) val west = StraightTrajectory2D(zero, vector(-2.0, 0.0)) - assertEquals(270.0, west.bearing.radiansToDegrees()) + assertEquals(270.0, west.bearing.degrees) } } From 6deeaf057e64d0ccaba0abb3cab32c64a8e76455 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 11 Feb 2023 21:51:19 +0300 Subject: [PATCH 30/72] Add angle serializer --- .../space/kscience/kmath/geometry/angles.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 index 45022ad05..3855514fb 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt @@ -5,10 +5,17 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import kotlin.jvm.JvmInline import kotlin.math.PI import kotlin.math.floor +@Serializable(AngleSerializer::class) public sealed interface Angle : Comparable { public fun toRadians(): Radians public fun toDegrees(): Degrees @@ -29,9 +36,21 @@ public sealed interface Angle : Comparable { } } + +public object AngleSerializer : KSerializer { + override val descriptor: SerialDescriptor get() = Double.serializer().descriptor + + override fun deserialize(decoder: Decoder): Angle = decoder.decodeDouble().degrees + + override fun serialize(encoder: Encoder, value: Angle) { + encoder.encodeDouble(value.degrees) + } +} + /** * Type safe radians */ +@Serializable @JvmInline public value class Radians(public val value: Double) : Angle { override fun toRadians(): Radians = this From 784d397ab12103bae441d770b8ee6c2f8e0c03c3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 12 Feb 2023 10:40:53 +0300 Subject: [PATCH 31/72] Fix serial names for trajectory serializers --- .../kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index b8916e748..7e0a8c1c0 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.trajectory +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import space.kscience.kmath.geometry.* @@ -21,6 +22,7 @@ public sealed interface Trajectory2D { * Straight path segment. The order of start and end defines the direction */ @Serializable +@SerialName("straight") public data class StraightTrajectory2D( public val start: DoubleVector2D, public val end: DoubleVector2D, @@ -34,6 +36,7 @@ public data class StraightTrajectory2D( * An arc segment */ @Serializable +@SerialName("arc") public data class CircleTrajectory2D( public val circle: Circle2D, public val start: DubinsPose2D, @@ -106,6 +109,7 @@ public data class CircleTrajectory2D( } @Serializable +@SerialName("composite") public class CompositeTrajectory2D(public val segments: List) : Trajectory2D { override val length: Double get() = segments.sumOf { it.length } } From 50579f4712695629d477eb1031f1a36e0d34f9af Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Mon, 13 Feb 2023 23:17:13 +0300 Subject: [PATCH 32/72] added tangent between two circles --- .../space/kscience/kmath/geometry/Tangent.kt | 77 +++++++++++++++++++ .../kscience/kmath/geometry/TangentTest.kt | 39 ++++++++++ 2 files changed, 116 insertions(+) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt create mode 100644 kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt new file mode 100644 index 000000000..889debecb --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2018-2023 KMath 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.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.linear.DoubleLinearSpace.plus +import space.kscience.kmath.linear.Point +import kotlin.math.absoluteValue +import kotlin.math.atan2 +import kotlin.math.pow +import kotlin.math.sign +import kotlin.math.sin +import kotlin.math.cos +import space.kscience.kmath.geometry.Euclidean2DSpace.vector +import space.kscience.kmath.geometry.Euclidean2DSpace.dot +import space.kscience.kmath.geometry.Euclidean2DSpace.scale +import space.kscience.kmath.geometry.Euclidean2DSpace.add + + +public class Segment( + public val startPoint: DoubleVector2D, + public val terminalPoint: DoubleVector2D, + public val length: Double = startPoint.distanceTo(terminalPoint) +) { + public override operator fun equals(other: Any?): Boolean { + return if (other is Segment) { + startPoint.x.equalFloat(other.startPoint.x) && startPoint.y.equalFloat(other.startPoint.y) && + terminalPoint.x.equalFloat(other.terminalPoint.x) && terminalPoint.y.equalFloat(other.terminalPoint.y) + } else { + false + } + } +} + +public const val maxFloatDelta: Double = 0.000001 +public fun Double.equalFloat(other: Double): Boolean = kotlin.math.abs(this - other) < maxFloatDelta + + + +public fun tangentsToCircles( + startCircle: Circle2D, + terminalCircle: Circle2D +): kotlin.collections.MutableMap { + val R1 = startCircle.radius + val R2 = terminalCircle.radius + val d = Segment(startCircle.center, terminalCircle.center).length + val angle1 = atan2(terminalCircle.center.x - startCircle.center.x, terminalCircle.center.y - startCircle.center.y) + var r: Double + var angle2: Double + val routes = mapOf("RSR" to Pair(R1, R2), + "RSL" to Pair(R1, -R2), + "LSR" to Pair(-R1, R2), + "LSL" to Pair(-R1, -R2)) + val segments = mutableMapOf() + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + val L = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, L) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, L) + } + val W = vector(-cos(angle2), sin(angle2)) + segments[route] = Segment(add(startCircle.center, scale(W, r1)), + add(terminalCircle.center, scale(W, r2))) + } + return segments +} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt new file mode 100644 index 000000000..beac8d15f --- /dev/null +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2018-2023 KMath 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.geometry.Euclidean2DSpace.vector +import kotlin.test.Test +import kotlin.test.assertEquals + +class TangentTest { + @Test + fun tangent() { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(4.0, 0.0), 1.0) + val routes = arrayListOf("RSR", "RSL", "LSR", "LSL") + val segments = arrayListOf( + Segment(startPoint = vector(0.0, 1.0), + terminalPoint = vector(4.0, 1.0)), + Segment(startPoint = vector(0.5, 0.8660254), + terminalPoint = vector(3.5, -0.8660254)), + Segment(startPoint = vector(0.5, -0.8660254), + terminalPoint = vector(3.5, 0.8660254)), + Segment(startPoint = vector(0.0, -1.0), + terminalPoint = vector(4.0, -1.0)) + ) + + val tangentMap = tangentsToCircles(c1, c2) + val tangentMapKeys = tangentMap.keys.toList() + val tangentMapValues = tangentMap.values.toList() + + assertEquals(routes, tangentMapKeys) + for (i in segments.indices) { + assertEquals(segments[i], tangentMapValues[i]) + } +// assertEquals(segments, tangentMapValues) + } +} \ No newline at end of file From bef317677c9a1c3496595dca8999a06ead1c3f85 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 14:36:58 +0300 Subject: [PATCH 33/72] tangentsToCircle fixed --- .../space/kscience/kmath/geometry/Circle2D.kt | 39 ++++++- .../space/kscience/kmath/geometry/Line.kt | 10 ++ .../space/kscience/kmath/geometry/Tangent.kt | 108 +++++++++--------- .../kscience/kmath/geometry/TangentTest.kt | 24 ++-- .../kscience/kmath/geometry/testUtils.kt | 3 + 5 files changed, 116 insertions(+), 68 deletions(-) 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 index 8beef6fee..a26a592da 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -6,7 +6,8 @@ package space.kscience.kmath.geometry import kotlinx.serialization.Serializable -import kotlin.math.PI +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import kotlin.math.* /** * A circle in 2D space @@ -17,4 +18,40 @@ public data class Circle2D( public val radius: Double ) +public fun Circle2D.tangentsToCircle(other: Circle2D): kotlin.collections.MutableMap> { + val R1 = this.radius + val R2 = other.radius + val line = LineSegment(this.center, other.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - this.center.x, other.center.y - this.center.y) + var r: Double + var angle2: Double + val routes = mapOf("RSR" to Pair(R1, R2), + "RSL" to Pair(R1, -R2), + "LSR" to Pair(-R1, R2), + "LSL" to Pair(-R1, -R2)) + val segments = mutableMapOf>() + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + val L = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, L) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, L) + } + val W = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + segments[route] = LineSegment( + Euclidean2DSpace.add(this.center, Euclidean2DSpace.scale(W, r1)), + Euclidean2DSpace.add(other.center, Euclidean2DSpace.scale(W, r2)) + ) + } + return segments +} + public val Circle2D.circumference: Double get() = radius * 2 * PI 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 ab322ddca..bb03b5a93 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 @@ -27,5 +27,15 @@ public fun LineSegment.line(algebra: GeometrySpace): Line Line(begin, end - begin) } +public fun equalLineSegments(line1: LineSegment, line2: LineSegment): Boolean { + val maxFloatDelta = 0.000001 + return line1.begin.x.equalFloat(line2.begin.x) && line1.begin.y.equalFloat(line2.begin.y) && + line1.end.x.equalFloat(line2.end.x) && line1.end.y.equalFloat(line2.end.y) +// return line1.begin == line2.begin && line1.end == line2.end +} + +public fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): + Boolean = kotlin.math.abs(this - other) < maxFloatDelta + public typealias LineSegment2D = LineSegment public typealias LineSegment3D = LineSegment diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt index 889debecb..cfcb78115 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt @@ -5,9 +5,6 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.linear.DoubleLinearSpace.plus -import space.kscience.kmath.linear.Point import kotlin.math.absoluteValue import kotlin.math.atan2 import kotlin.math.pow @@ -15,63 +12,64 @@ import kotlin.math.sign import kotlin.math.sin import kotlin.math.cos import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.geometry.Euclidean2DSpace.dot import space.kscience.kmath.geometry.Euclidean2DSpace.scale import space.kscience.kmath.geometry.Euclidean2DSpace.add +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -public class Segment( - public val startPoint: DoubleVector2D, - public val terminalPoint: DoubleVector2D, - public val length: Double = startPoint.distanceTo(terminalPoint) -) { - public override operator fun equals(other: Any?): Boolean { - return if (other is Segment) { - startPoint.x.equalFloat(other.startPoint.x) && startPoint.y.equalFloat(other.startPoint.y) && - terminalPoint.x.equalFloat(other.terminalPoint.x) && terminalPoint.y.equalFloat(other.terminalPoint.y) - } else { - false - } - } -} +//public class Segment( +// public val startPoint: DoubleVector2D, +// public val terminalPoint: DoubleVector2D, +// public val length: Double = startPoint.distanceTo(terminalPoint) +//) { +// public override operator fun equals(other: Any?): Boolean { +// return if (other is Segment) { +// startPoint.x.equalFloat(other.startPoint.x) && startPoint.y.equalFloat(other.startPoint.y) && +// terminalPoint.x.equalFloat(other.terminalPoint.x) && terminalPoint.y.equalFloat(other.terminalPoint.y) +// } else { +// false +// } +// } +//} -public const val maxFloatDelta: Double = 0.000001 -public fun Double.equalFloat(other: Double): Boolean = kotlin.math.abs(this - other) < maxFloatDelta +//public const val maxFloatDelta: Double = 0.000001 +//public fun Double.equalFloat(other: Double): Boolean = kotlin.math.abs(this - other) < maxFloatDelta -public fun tangentsToCircles( - startCircle: Circle2D, - terminalCircle: Circle2D -): kotlin.collections.MutableMap { - val R1 = startCircle.radius - val R2 = terminalCircle.radius - val d = Segment(startCircle.center, terminalCircle.center).length - val angle1 = atan2(terminalCircle.center.x - startCircle.center.x, terminalCircle.center.y - startCircle.center.y) - var r: Double - var angle2: Double - val routes = mapOf("RSR" to Pair(R1, R2), - "RSL" to Pair(R1, -R2), - "LSR" to Pair(-R1, R2), - "LSL" to Pair(-R1, -R2)) - val segments = mutableMapOf() - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - val L = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, L) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, L) - } - val W = vector(-cos(angle2), sin(angle2)) - segments[route] = Segment(add(startCircle.center, scale(W, r1)), - add(terminalCircle.center, scale(W, r2))) - } - return segments -} \ No newline at end of file +//public fun tangentsToCircles( +// startCircle: Circle2D, +// terminalCircle: Circle2D +//): kotlin.collections.MutableMap> { +// val R1 = startCircle.radius +// val R2 = terminalCircle.radius +// val line = LineSegment(startCircle.center, terminalCircle.center) +// val d = line.begin.distanceTo(line.end) +// val angle1 = atan2(terminalCircle.center.x - startCircle.center.x, terminalCircle.center.y - startCircle.center.y) +// var r: Double +// var angle2: Double +// val routes = mapOf("RSR" to Pair(R1, R2), +// "RSL" to Pair(R1, -R2), +// "LSR" to Pair(-R1, R2), +// "LSL" to Pair(-R1, -R2)) +// val segments = mutableMapOf>() +// for ((route, r1r2) in routes) { +// val r1 = r1r2.first +// val r2 = r1r2.second +// r = if (r1.sign == r2.sign) { +// r1.absoluteValue - r2.absoluteValue +// } else { +// r1.absoluteValue + r2.absoluteValue +// } +// val L = (d * d - r * r).pow(0.5) +// angle2 = if (r1.absoluteValue > r2.absoluteValue) { +// angle1 + r1.sign * atan2(r.absoluteValue, L) +// } else { +// angle1 - r2.sign * atan2(r.absoluteValue, L) +// } +// val W = vector(-cos(angle2), sin(angle2)) +// segments[route] = LineSegment(add(startCircle.center, scale(W, r1)), +// add(terminalCircle.center, scale(W, r2))) +// } +// return segments +//} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt index beac8d15f..fd3002e19 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.geometry import space.kscience.kmath.geometry.Euclidean2DSpace.vector import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue class TangentTest { @Test @@ -15,25 +16,24 @@ class TangentTest { val c1 = Circle2D(vector(0.0, 0.0), 1.0) val c2 = Circle2D(vector(4.0, 0.0), 1.0) val routes = arrayListOf("RSR", "RSL", "LSR", "LSL") - val segments = arrayListOf( - Segment(startPoint = vector(0.0, 1.0), - terminalPoint = vector(4.0, 1.0)), - Segment(startPoint = vector(0.5, 0.8660254), - terminalPoint = vector(3.5, -0.8660254)), - Segment(startPoint = vector(0.5, -0.8660254), - terminalPoint = vector(3.5, 0.8660254)), - Segment(startPoint = vector(0.0, -1.0), - terminalPoint = vector(4.0, -1.0)) + val segments = arrayListOf>( + LineSegment(begin = vector(0.0, 1.0), + end = vector(4.0, 1.0)), + LineSegment(begin = vector(0.5, 0.8660254), + end = vector(3.5, -0.8660254)), + LineSegment(begin = vector(0.5, -0.8660254), + end = vector(3.5, 0.8660254)), + LineSegment(begin = vector(0.0, -1.0), + end = vector(4.0, -1.0)) ) - val tangentMap = tangentsToCircles(c1, c2) + val tangentMap = c1.tangentsToCircle(c2) val tangentMapKeys = tangentMap.keys.toList() val tangentMapValues = tangentMap.values.toList() assertEquals(routes, tangentMapKeys) for (i in segments.indices) { - assertEquals(segments[i], tangentMapValues[i]) + assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) } -// assertEquals(segments, tangentMapValues) } } \ No newline at end of file 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 89db22d45..c62af3cd3 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 @@ -44,3 +44,6 @@ fun GeometrySpace.isCollinear(a: V, b: V, absoluteTolerance: Dou fun GeometrySpace.isOrthogonal(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean = abs(a dot b) < absoluteTolerance + +fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): + Boolean = kotlin.math.abs(this - other) < maxFloatDelta \ No newline at end of file From d535a2155f3171b538a2f6019dffad9ef83f2001 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 15:06:47 +0300 Subject: [PATCH 34/72] tangentsToCircle fixed --- .../space/kscience/kmath/geometry/Circle2D.kt | 17 +++-- .../kmath/geometry/Euclidean2DSpace.kt | 7 ++ .../space/kscience/kmath/geometry/Line.kt | 6 -- .../space/kscience/kmath/geometry/Tangent.kt | 75 ------------------- .../kscience/kmath/geometry/TangentTest.kt | 8 +- 5 files changed, 25 insertions(+), 88 deletions(-) delete mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt 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 index a26a592da..df25dcbea 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -18,7 +18,11 @@ public data class Circle2D( public val radius: Double ) -public fun Circle2D.tangentsToCircle(other: Circle2D): kotlin.collections.MutableMap> { +public enum class DubinsRoutes { + RSR, RSL, LSR, LSL +} + +public fun Circle2D.tangentsToCircle(other: Circle2D): Map> { val R1 = this.radius val R2 = other.radius val line = LineSegment(this.center, other.center) @@ -26,11 +30,12 @@ public fun Circle2D.tangentsToCircle(other: Circle2D): kotlin.collections.Mutabl val angle1 = atan2(other.center.x - this.center.x, other.center.y - this.center.y) var r: Double var angle2: Double - val routes = mapOf("RSR" to Pair(R1, R2), - "RSL" to Pair(R1, -R2), - "LSR" to Pair(-R1, R2), - "LSL" to Pair(-R1, -R2)) - val segments = mutableMapOf>() + val routes = mapOf( + DubinsRoutes.RSR to Pair(R1, R2), + DubinsRoutes.RSL to Pair(R1, -R2), + DubinsRoutes.LSR to Pair(-R1, R2), + DubinsRoutes.LSL to Pair(-R1, -R2)) + val segments = mutableMapOf>() for ((route, r1r2) in routes) { val r1 = r1r2.first val r2 = r1r2.second 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 3df8dba7b..dc05f6648 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 @@ -85,6 +85,13 @@ public object Euclidean2DSpace : GeometrySpace, 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 fun equalLineSegments(line1: LineSegment, line2: LineSegment): Boolean { + val maxFloatDelta = 0.000001 + return line1.begin.x.equalFloat(line2.begin.x) && line1.begin.y.equalFloat(line2.begin.y) && + line1.end.x.equalFloat(line2.end.x) && line1.end.y.equalFloat(line2.end.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/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index bb03b5a93..6413edce9 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 @@ -27,12 +27,6 @@ public fun LineSegment.line(algebra: GeometrySpace): Line Line(begin, end - begin) } -public fun equalLineSegments(line1: LineSegment, line2: LineSegment): Boolean { - val maxFloatDelta = 0.000001 - return line1.begin.x.equalFloat(line2.begin.x) && line1.begin.y.equalFloat(line2.begin.y) && - line1.end.x.equalFloat(line2.end.x) && line1.end.y.equalFloat(line2.end.y) -// return line1.begin == line2.begin && line1.end == line2.end -} public fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): Boolean = kotlin.math.abs(this - other) < maxFloatDelta diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt deleted file mode 100644 index cfcb78115..000000000 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Tangent.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.absoluteValue -import kotlin.math.atan2 -import kotlin.math.pow -import kotlin.math.sign -import kotlin.math.sin -import kotlin.math.cos -import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.geometry.Euclidean2DSpace.scale -import space.kscience.kmath.geometry.Euclidean2DSpace.add -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo - - -//public class Segment( -// public val startPoint: DoubleVector2D, -// public val terminalPoint: DoubleVector2D, -// public val length: Double = startPoint.distanceTo(terminalPoint) -//) { -// public override operator fun equals(other: Any?): Boolean { -// return if (other is Segment) { -// startPoint.x.equalFloat(other.startPoint.x) && startPoint.y.equalFloat(other.startPoint.y) && -// terminalPoint.x.equalFloat(other.terminalPoint.x) && terminalPoint.y.equalFloat(other.terminalPoint.y) -// } else { -// false -// } -// } -//} - -//public const val maxFloatDelta: Double = 0.000001 -//public fun Double.equalFloat(other: Double): Boolean = kotlin.math.abs(this - other) < maxFloatDelta - - - -//public fun tangentsToCircles( -// startCircle: Circle2D, -// terminalCircle: Circle2D -//): kotlin.collections.MutableMap> { -// val R1 = startCircle.radius -// val R2 = terminalCircle.radius -// val line = LineSegment(startCircle.center, terminalCircle.center) -// val d = line.begin.distanceTo(line.end) -// val angle1 = atan2(terminalCircle.center.x - startCircle.center.x, terminalCircle.center.y - startCircle.center.y) -// var r: Double -// var angle2: Double -// val routes = mapOf("RSR" to Pair(R1, R2), -// "RSL" to Pair(R1, -R2), -// "LSR" to Pair(-R1, R2), -// "LSL" to Pair(-R1, -R2)) -// val segments = mutableMapOf>() -// for ((route, r1r2) in routes) { -// val r1 = r1r2.first -// val r2 = r1r2.second -// r = if (r1.sign == r2.sign) { -// r1.absoluteValue - r2.absoluteValue -// } else { -// r1.absoluteValue + r2.absoluteValue -// } -// val L = (d * d - r * r).pow(0.5) -// angle2 = if (r1.absoluteValue > r2.absoluteValue) { -// angle1 + r1.sign * atan2(r.absoluteValue, L) -// } else { -// angle1 - r2.sign * atan2(r.absoluteValue, L) -// } -// val W = vector(-cos(angle2), sin(angle2)) -// segments[route] = LineSegment(add(startCircle.center, scale(W, r1)), -// add(terminalCircle.center, scale(W, r2))) -// } -// return segments -//} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt index fd3002e19..214495dfe 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.geometry +import space.kscience.kmath.geometry.Euclidean2DSpace.equalLineSegments import space.kscience.kmath.geometry.Euclidean2DSpace.vector import kotlin.test.Test import kotlin.test.assertEquals @@ -15,7 +16,12 @@ class TangentTest { fun tangent() { val c1 = Circle2D(vector(0.0, 0.0), 1.0) val c2 = Circle2D(vector(4.0, 0.0), 1.0) - val routes = arrayListOf("RSR", "RSL", "LSR", "LSL") + val routes = arrayListOf( + DubinsRoutes.RSR, + DubinsRoutes.RSL, + DubinsRoutes.LSR, + DubinsRoutes.LSL + ) val segments = arrayListOf>( LineSegment(begin = vector(0.0, 1.0), end = vector(4.0, 1.0)), From c342c5cd7835c92a7ccd26d07872b8018f7980f2 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 17:53:32 +0300 Subject: [PATCH 35/72] tangentsToCircle fixed --- .../space/kscience/kmath/geometry/Circle2D.kt | 40 ---------- .../kscience/kmath/geometry/TangentTest.kt | 80 +++++++++---------- .../kscience/kmath/trajectory/Tangent.kt | 55 +++++++++++++ .../kmath/trajectory/segments/TangentTest.kt | 48 +++++++++++ 4 files changed, 143 insertions(+), 80 deletions(-) create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt 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 index df25dcbea..d37ed45c0 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -18,45 +18,5 @@ public data class Circle2D( public val radius: Double ) -public enum class DubinsRoutes { - RSR, RSL, LSR, LSL -} - -public fun Circle2D.tangentsToCircle(other: Circle2D): Map> { - val R1 = this.radius - val R2 = other.radius - val line = LineSegment(this.center, other.center) - val d = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - this.center.x, other.center.y - this.center.y) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsRoutes.RSR to Pair(R1, R2), - DubinsRoutes.RSL to Pair(R1, -R2), - DubinsRoutes.LSR to Pair(-R1, R2), - DubinsRoutes.LSL to Pair(-R1, -R2)) - val segments = mutableMapOf>() - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - val L = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, L) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, L) - } - val W = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) - segments[route] = LineSegment( - Euclidean2DSpace.add(this.center, Euclidean2DSpace.scale(W, r1)), - Euclidean2DSpace.add(other.center, Euclidean2DSpace.scale(W, r2)) - ) - } - return segments -} public val Circle2D.circumference: Double get() = radius * 2 * PI diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt index 214495dfe..4ffd4dcab 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt @@ -3,43 +3,43 @@ * 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.geometry.Euclidean2DSpace.equalLineSegments -import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class TangentTest { - @Test - fun tangent() { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(4.0, 0.0), 1.0) - val routes = arrayListOf( - DubinsRoutes.RSR, - DubinsRoutes.RSL, - DubinsRoutes.LSR, - DubinsRoutes.LSL - ) - val segments = arrayListOf>( - LineSegment(begin = vector(0.0, 1.0), - end = vector(4.0, 1.0)), - LineSegment(begin = vector(0.5, 0.8660254), - end = vector(3.5, -0.8660254)), - LineSegment(begin = vector(0.5, -0.8660254), - end = vector(3.5, 0.8660254)), - LineSegment(begin = vector(0.0, -1.0), - end = vector(4.0, -1.0)) - ) - - val tangentMap = c1.tangentsToCircle(c2) - val tangentMapKeys = tangentMap.keys.toList() - val tangentMapValues = tangentMap.values.toList() - - assertEquals(routes, tangentMapKeys) - for (i in segments.indices) { - assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) - } - } -} \ No newline at end of file +//package space.kscience.kmath.geometry +// +//import space.kscience.kmath.geometry.Euclidean2DSpace.equalLineSegments +//import space.kscience.kmath.geometry.Euclidean2DSpace.vector +//import kotlin.test.Test +//import kotlin.test.assertEquals +//import kotlin.test.assertTrue +// +//class TangentTest { +// @Test +// fun tangent() { +// val c1 = Circle2D(vector(0.0, 0.0), 1.0) +// val c2 = Circle2D(vector(4.0, 0.0), 1.0) +// val routes = arrayListOf( +// DubinsRoutes.RSR, +// DubinsRoutes.RSL, +// DubinsRoutes.LSR, +// DubinsRoutes.LSL +// ) +// val segments = arrayListOf>( +// LineSegment(begin = vector(0.0, 1.0), +// end = vector(4.0, 1.0)), +// LineSegment(begin = vector(0.5, 0.8660254), +// end = vector(3.5, -0.8660254)), +// LineSegment(begin = vector(0.5, -0.8660254), +// end = vector(3.5, 0.8660254)), +// LineSegment(begin = vector(0.0, -1.0), +// end = vector(4.0, -1.0)) +// ) +// +// val tangentMap = c1.tangentsToCircle(c2) +// val tangentMapKeys = tangentMap.keys.toList() +// val tangentMapValues = tangentMap.values.toList() +// +// assertEquals(routes, tangentMapKeys) +// for (i in segments.indices) { +// assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) +// } +// } +//} \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt new file mode 100644 index 000000000..9546a8d64 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2018-2023 KMath 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 +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.LineSegment +import kotlin.math.* + +public enum class DubinsRoutes { + RSR, RSL, LSR, LSL +} + +public fun Circle2D.tangentsToCircle(other: Circle2D): Map> { + val R1 = this.radius + val R2 = other.radius + val line = LineSegment(this.center, other.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - this.center.x, other.center.y - this.center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsRoutes.RSR to Pair(R1, R2), + DubinsRoutes.RSL to Pair(R1, -R2), + DubinsRoutes.LSR to Pair(-R1, R2), + DubinsRoutes.LSL to Pair(-R1, -R2) + ) + val segments = mutableMapOf>() + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + val L = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, L) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, L) + } + val W = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + segments[route] = LineSegment( + Euclidean2DSpace.add(this.center, Euclidean2DSpace.scale(W, r1)), + Euclidean2DSpace.add(other.center, Euclidean2DSpace.scale(W, r2)) + ) + } + return segments +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt new file mode 100644 index 000000000..cfa2fa52b --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2018-2023 KMath 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.equalLineSegments +import space.kscience.kmath.geometry.Euclidean2DSpace.vector +import space.kscience.kmath.geometry.LineSegment +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TangentTest { + @Test + fun tangent() { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(4.0, 0.0), 1.0) + val routes = arrayListOf( + DubinsRoutes.RSR, + DubinsRoutes.RSL, + DubinsRoutes.LSR, + DubinsRoutes.LSL + ) + val segments = arrayListOf>( + LineSegment(begin = vector(0.0, 1.0), + end = vector(4.0, 1.0)), + LineSegment(begin = vector(0.5, 0.8660254), + end = vector(3.5, -0.8660254)), + LineSegment(begin = vector(0.5, -0.8660254), + end = vector(3.5, 0.8660254)), + LineSegment(begin = vector(0.0, -1.0), + end = vector(4.0, -1.0)) + ) + + val tangentMap = c1.tangentsToCircle(c2) + val tangentMapKeys = tangentMap.keys.toList() + val tangentMapValues = tangentMap.values.toList() + + assertEquals(routes, tangentMapKeys) + for (i in segments.indices) { + assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) + } + } +} \ No newline at end of file From 8998a394b34e6946f820d27521b40cd67ba3a33f Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 17:55:39 +0300 Subject: [PATCH 36/72] tangentsToCircle fixed --- .../space/kscience/kmath/geometry/Line.kt | 1 - .../kscience/kmath/geometry/TangentTest.kt | 45 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt 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 6413edce9..adc3a8b85 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 @@ -27,7 +27,6 @@ public fun LineSegment.line(algebra: GeometrySpace): Line Line(begin, end - begin) } - public fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): Boolean = kotlin.math.abs(this - other) < maxFloatDelta diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt deleted file mode 100644 index 4ffd4dcab..000000000 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/TangentTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.geometry.Euclidean2DSpace.equalLineSegments -//import space.kscience.kmath.geometry.Euclidean2DSpace.vector -//import kotlin.test.Test -//import kotlin.test.assertEquals -//import kotlin.test.assertTrue -// -//class TangentTest { -// @Test -// fun tangent() { -// val c1 = Circle2D(vector(0.0, 0.0), 1.0) -// val c2 = Circle2D(vector(4.0, 0.0), 1.0) -// val routes = arrayListOf( -// DubinsRoutes.RSR, -// DubinsRoutes.RSL, -// DubinsRoutes.LSR, -// DubinsRoutes.LSL -// ) -// val segments = arrayListOf>( -// LineSegment(begin = vector(0.0, 1.0), -// end = vector(4.0, 1.0)), -// LineSegment(begin = vector(0.5, 0.8660254), -// end = vector(3.5, -0.8660254)), -// LineSegment(begin = vector(0.5, -0.8660254), -// end = vector(3.5, 0.8660254)), -// LineSegment(begin = vector(0.0, -1.0), -// end = vector(4.0, -1.0)) -// ) -// -// val tangentMap = c1.tangentsToCircle(c2) -// val tangentMapKeys = tangentMap.keys.toList() -// val tangentMapValues = tangentMap.values.toList() -// -// assertEquals(routes, tangentMapKeys) -// for (i in segments.indices) { -// assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) -// } -// } -//} \ No newline at end of file From 7d897ad8cb6758b57d9bc08d3ec7250caae944dc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:29:12 +0300 Subject: [PATCH 37/72] Cleanup after circle tangent changes --- .../kmath/geometry/Euclidean2DSpace.kt | 7 --- .../space/kscience/kmath/geometry/Line.kt | 3 - .../kscience/kmath/geometry/floatPrecision.kt | 38 +++++++++++++ .../kscience/kmath/trajectory/Tangent.kt | 55 ------------------ .../kscience/kmath/trajectory/tangent.kt | 53 ++++++++++++++++++ .../kscience/kmath/trajectory/TangentTest.kt | 56 +++++++++++++++++++ .../kmath/trajectory/segments/TangentTest.kt | 48 ---------------- 7 files changed, 147 insertions(+), 113 deletions(-) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt 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 dc05f6648..3df8dba7b 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 @@ -85,13 +85,6 @@ public object Euclidean2DSpace : GeometrySpace, 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 fun equalLineSegments(line1: LineSegment, line2: LineSegment): Boolean { - val maxFloatDelta = 0.000001 - return line1.begin.x.equalFloat(line2.begin.x) && line1.begin.y.equalFloat(line2.begin.y) && - line1.end.x.equalFloat(line2.end.x) && line1.end.y.equalFloat(line2.end.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/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index adc3a8b85..ab322ddca 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 @@ -27,8 +27,5 @@ public fun LineSegment.line(algebra: GeometrySpace): Line Line(begin, end - begin) } -public fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): - Boolean = kotlin.math.abs(this - other) < maxFloatDelta - public typealias LineSegment2D = LineSegment public typealias LineSegment3D = LineSegment diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt new file mode 100644 index 000000000..023355a0f --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2023 KMath 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 + +internal const val defaultPrecision = 1e-6 + +public fun Double.equalsFloat(other: Double, precision: Double = defaultPrecision): Boolean = + kotlin.math.abs(this - other) < precision + +public fun Double.equalsFloat(other: Float, precision: Double = defaultPrecision): Boolean = + kotlin.math.abs(this - other) < precision + +public fun V.equalsVector( + space: GeometrySpace, + other: V, + precision: Double = defaultPrecision, +): Boolean = with(space) { + norm(this@equalsVector - other) < precision +} + +public fun Float64Vector2D.equalsVector( + other: Float64Vector2D, + precision: Double = defaultPrecision, +): Boolean = equalsVector(Euclidean2DSpace, other, precision) + +public fun Float64Vector3D.equalsVector( + other: Float64Vector3D, + precision: Double = defaultPrecision, +): Boolean = equalsVector(Euclidean3DSpace, other, precision) + +public fun LineSegment.equalsLine( + space: GeometrySpace, + other: LineSegment, + precision: Double = defaultPrecision, +): Boolean = begin.equalsVector(space, other.begin, precision) && end.equalsVector(space, other.end, precision) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt deleted file mode 100644 index 9546a8d64..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Tangent.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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 -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.LineSegment -import kotlin.math.* - -public enum class DubinsRoutes { - RSR, RSL, LSR, LSL -} - -public fun Circle2D.tangentsToCircle(other: Circle2D): Map> { - val R1 = this.radius - val R2 = other.radius - val line = LineSegment(this.center, other.center) - val d = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - this.center.x, other.center.y - this.center.y) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsRoutes.RSR to Pair(R1, R2), - DubinsRoutes.RSL to Pair(R1, -R2), - DubinsRoutes.LSR to Pair(-R1, R2), - DubinsRoutes.LSL to Pair(-R1, -R2) - ) - val segments = mutableMapOf>() - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - val L = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, L) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, L) - } - val W = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) - segments[route] = LineSegment( - Euclidean2DSpace.add(this.center, Euclidean2DSpace.scale(W, r1)), - Euclidean2DSpace.add(other.center, Euclidean2DSpace.scale(W, r2)) - ) - } - return segments -} \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt new file mode 100644 index 000000000..70a1ac696 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2018-2023 KMath 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 +import space.kscience.kmath.geometry.LineSegment +import kotlin.math.* + +public fun Circle2D.tangentsToCircle( + other: Circle2D, +): Map> = with(Euclidean2DSpace) { + val line = LineSegment(center, other.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(radius, other.radius), + DubinsPath.Type.RSL to Pair(radius, -other.radius), + DubinsPath.Type.LSR to Pair(-radius, other.radius), + DubinsPath.Type.LSL to Pair(-radius, -other.radius) + ) + return buildMap { + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + val l = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put( + route, + LineSegment( + center + w * r1, + other.center + w * r2 + ) + ) + } + } +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt new file mode 100644 index 000000000..c1cf2f800 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2018-2023 KMath 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.vector +import space.kscience.kmath.geometry.LineSegment +import space.kscience.kmath.geometry.equalsLine +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TangentTest { + @Test + fun tangent() { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(4.0, 0.0), 1.0) + val routes = listOf( + DubinsPath.Type.RSR, + DubinsPath.Type.RSL, + DubinsPath.Type.LSR, + DubinsPath.Type.LSL + ) + val segments = listOf( + LineSegment( + begin = vector(0.0, 1.0), + end = vector(4.0, 1.0) + ), + LineSegment( + begin = vector(0.5, 0.8660254), + end = vector(3.5, -0.8660254) + ), + LineSegment( + begin = vector(0.5, -0.8660254), + end = vector(3.5, 0.8660254) + ), + LineSegment( + begin = vector(0.0, -1.0), + end = vector(4.0, -1.0) + ) + ) + + val tangentMap = c1.tangentsToCircle(c2) + val tangentMapKeys = tangentMap.keys.toList() + val tangentMapValues = tangentMap.values.toList() + + assertEquals(routes, tangentMapKeys) + for (i in segments.indices) { + assertTrue(segments[i].equalsLine(Euclidean2DSpace, tangentMapValues[i])) + } + } +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt deleted file mode 100644 index cfa2fa52b..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/TangentTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.equalLineSegments -import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.geometry.LineSegment -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class TangentTest { - @Test - fun tangent() { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(4.0, 0.0), 1.0) - val routes = arrayListOf( - DubinsRoutes.RSR, - DubinsRoutes.RSL, - DubinsRoutes.LSR, - DubinsRoutes.LSL - ) - val segments = arrayListOf>( - LineSegment(begin = vector(0.0, 1.0), - end = vector(4.0, 1.0)), - LineSegment(begin = vector(0.5, 0.8660254), - end = vector(3.5, -0.8660254)), - LineSegment(begin = vector(0.5, -0.8660254), - end = vector(3.5, 0.8660254)), - LineSegment(begin = vector(0.0, -1.0), - end = vector(4.0, -1.0)) - ) - - val tangentMap = c1.tangentsToCircle(c2) - val tangentMapKeys = tangentMap.keys.toList() - val tangentMapValues = tangentMap.values.toList() - - assertEquals(routes, tangentMapKeys) - for (i in segments.indices) { - assertTrue(equalLineSegments(segments[i], tangentMapValues[i])) - } - } -} \ No newline at end of file From 67316c4a70cee2814ef2e65dece45077bef7c894 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:39:25 +0300 Subject: [PATCH 38/72] Add documentation after circle tangent changes --- .../kscience/kmath/geometry/GeometrySpace.kt | 7 ++++ .../kscience/kmath/geometry/floatPrecision.kt | 32 +++++++++++++++---- .../kscience/kmath/trajectory/tangent.kt | 4 +++ 3 files changed, 36 insertions(+), 7 deletions(-) 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 854d84b65..d6d7e5725 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 @@ -21,4 +21,11 @@ public interface GeometrySpace : Group, ScaleOperations, Norm< * Scalar product */ public infix fun V.dot(other: V): Double + + public companion object{ + /** + * Default precision for geometry objects comparison + */ + internal const val DEFAULT_PRECISION = 1e-6 + } } \ No newline at end of file diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt index 023355a0f..ea46ab90f 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt @@ -5,34 +5,52 @@ package space.kscience.kmath.geometry -internal const val defaultPrecision = 1e-6 +import space.kscience.kmath.geometry.GeometrySpace.Companion.DEFAULT_PRECISION -public fun Double.equalsFloat(other: Double, precision: Double = defaultPrecision): Boolean = +/** + * Float equality within given [precision] + */ +public fun Double.equalsFloat(other: Double, precision: Double = DEFAULT_PRECISION): Boolean = kotlin.math.abs(this - other) < precision -public fun Double.equalsFloat(other: Float, precision: Double = defaultPrecision): Boolean = +/** + * Float equality within given [precision] + */ +public fun Double.equalsFloat(other: Float, precision: Double = DEFAULT_PRECISION): Boolean = kotlin.math.abs(this - other) < precision +/** + * Vector equality within given [precision] (using [GeometrySpace.norm] provided by the space + */ public fun V.equalsVector( space: GeometrySpace, other: V, - precision: Double = defaultPrecision, + precision: Double = DEFAULT_PRECISION, ): Boolean = with(space) { norm(this@equalsVector - other) < precision } +/** + * Vector equality using Euclidian L2 norm and given [precision] + */ public fun Float64Vector2D.equalsVector( other: Float64Vector2D, - precision: Double = defaultPrecision, + precision: Double = DEFAULT_PRECISION, ): Boolean = equalsVector(Euclidean2DSpace, other, precision) +/** + * Vector equality using Euclidian L2 norm and given [precision] + */ public fun Float64Vector3D.equalsVector( other: Float64Vector3D, - precision: Double = defaultPrecision, + precision: Double = DEFAULT_PRECISION, ): Boolean = equalsVector(Euclidean3DSpace, other, precision) +/** + * Line equality using [GeometrySpace.norm] provided by the [space] and given [precision] + */ public fun LineSegment.equalsLine( space: GeometrySpace, other: LineSegment, - precision: Double = defaultPrecision, + precision: Double = DEFAULT_PRECISION, ): Boolean = begin.equalsVector(space, other.begin, precision) && end.equalsVector(space, other.end, precision) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index 70a1ac696..cf5bcd11d 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -11,6 +11,10 @@ import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.LineSegment import kotlin.math.* +/** + * Create inner and outer tangents between two circles. + * This method returns a map of segments using [DubinsPath] connection type notation. + */ public fun Circle2D.tangentsToCircle( other: Circle2D, ): Map> = with(Euclidean2DSpace) { From ed4aa47913c2cc982e9a325e3635774d00d01dec Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:57:24 +0300 Subject: [PATCH 39/72] Minor refactoring of tangents --- .../space/kscience/kmath/trajectory/Trajectory2D.kt | 4 +--- .../space/kscience/kmath/trajectory/TangentTest.kt | 2 +- .../kscience/kmath/trajectory/dubins/DubinsTests.kt | 3 ++- .../kotlin/space/kscience/kmath/trajectory/math.kt | 10 +++------- .../kscience/kmath/trajectory/segments/ArcTests.kt | 7 ++++++- .../kscience/kmath/trajectory/segments/CircleTests.kt | 3 +-- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 7e0a8c1c0..e5f60e025 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -100,9 +100,7 @@ public data class CircleTrajectory2D( val pose1 = calculatePose(start, s1.bearing, direction) val pose2 = calculatePose(end, s2.bearing, direction) val trajectory = CircleTrajectory2D(Circle2D(center, s1.length), pose1, pose2) - if (trajectory.direction != direction) { - error("Trajectory direction mismatch") - } + if (trajectory.direction != direction) error("Trajectory direction mismatch") return trajectory } } diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt index c1cf2f800..42442a55f 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt @@ -16,7 +16,7 @@ import kotlin.test.assertTrue class TangentTest { @Test - fun tangent() { + fun tangents() { val c1 = Circle2D(vector(0.0, 0.0), 1.0) val c2 = Circle2D(vector(4.0, 0.0), 1.0) val routes = listOf( 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 index 0e14ae736..481ea4786 100644 --- 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.trajectory.dubins import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.equalsFloat import space.kscience.kmath.trajectory.* import kotlin.test.Test import kotlin.test.assertNotNull @@ -39,7 +40,7 @@ class DubinsTests { val path = dubins.find { p -> DubinsPath.trajectoryTypeOf(p) === it.key } assertNotNull(path, "Path ${it.key} not found") println("${it.key}: ${path.length}") - assertTrue(it.value.equalFloat(path.length)) + assertTrue(it.value.equalsFloat(path.length)) val a = path.segments[0] as CircleTrajectory2D val b = path.segments[1] 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 index c69ad24f1..24685f528 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt @@ -6,20 +6,16 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.equalsFloat import space.kscience.kmath.geometry.radians import space.kscience.kmath.geometry.sin -import kotlin.math.PI -import kotlin.math.abs -const val maxFloatDelta = 0.000001 -fun Double.radiansToDegrees() = this * 180 / PI - -fun Double.equalFloat(other: Double) = abs(this - other) < maxFloatDelta fun DubinsPose2D.equalsFloat(other: DubinsPose2D) = - x.equalFloat(other.x) && y.equalFloat(other.y) && bearing.radians.equalFloat(other.bearing.radians) + x.equalsFloat(other.x) && y.equalsFloat(other.y) && bearing.radians.equalsFloat(other.bearing.radians) fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, start) + fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace) { val dX = width * sin(inverse().bearing) val dY = width * sin(bearing) 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 index 643f9eaaa..7594aa046 100644 --- 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 @@ -18,7 +18,12 @@ class ArcTests { @Test fun arcTest() = with(Euclidean2DSpace){ val circle = Circle2D(vector(0.0, 0.0), 2.0) - val arc = CircleTrajectory2D.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), CircleTrajectory2D.Direction.RIGHT) + val arc = CircleTrajectory2D.of( + circle.center, + vector(-2.0, 0.0), + vector(0.0, 2.0), + CircleTrajectory2D.Direction.RIGHT + ) assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.start.bearing.degrees) assertEquals(90.0, arc.end.bearing.degrees) 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 index 5321fb1a1..27434b874 100644 --- 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 @@ -8,7 +8,6 @@ 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 @@ -20,6 +19,6 @@ class CircleTests { val radius = 2.0 val expectedCircumference = 12.56637 val circle = Circle2D(center, radius) - assertEquals(expectedCircumference, circle.circumference, maxFloatDelta) + assertEquals(expectedCircumference, circle.circumference) } } From cc0fb2a718a3981332328b75ce2a86b4610b161d Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 16 Feb 2023 18:47:42 +0300 Subject: [PATCH 40/72] non-existence of tangents throws exception --- .../kscience/kmath/trajectory/tangent.kt | 31 +++++++++++-------- .../kscience/kmath/trajectory/TangentTest.kt | 25 +++++++++++++++ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index cf5bcd11d..945b140c2 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -38,20 +38,25 @@ public fun Circle2D.tangentsToCircle( } else { r1.absoluteValue + r2.absoluteValue } - val l = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - route, - LineSegment( - center + w * r1, - other.center + w * r2 + if (d * d > r * r) { + val l = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put( + route, + LineSegment( + center + w * r1, + other.center + w * r2 + ) ) - ) + } + else { + throw Exception("Circles should not be") + } } } } \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt index 42442a55f..3e87b47de 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt @@ -13,6 +13,7 @@ import space.kscience.kmath.geometry.equalsLine import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +import kotlin.test.assertFailsWith class TangentTest { @Test @@ -53,4 +54,28 @@ class TangentTest { assertTrue(segments[i].equalsLine(Euclidean2DSpace, tangentMapValues[i])) } } + + @Test + fun nonExistingTangents() { + assertFailsWith { + val c1 = Circle2D(vector(0.0, 0.0), 10.0) + val c2 = Circle2D(vector(0.0, 0.0), 1.0) + val segments = c1.tangentsToCircle(c2) + } + assertFailsWith { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(0.0, 0.0), 10.0) + val segments = c1.tangentsToCircle(c2) + } + assertFailsWith { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(2.0, 0.0), 1.0) + val segments = c1.tangentsToCircle(c2) + } + assertFailsWith { + val c1 = Circle2D(vector(0.0, 0.0), 1.0) + val c2 = Circle2D(vector(0.5, 0.0), 1.0) + val segments = c1.tangentsToCircle(c2) + } + } } \ No newline at end of file From 04127fc3f2b781a2e66b95b8b2d63629dca15220 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 18 Feb 2023 18:53:03 +0300 Subject: [PATCH 41/72] Fix tests --- gradle.properties | 2 +- .../kscience/kmath/trajectory/tangent.kt | 48 +++++++++---------- .../kscience/kmath/trajectory/TangentTest.kt | 40 +++++++--------- .../kmath/trajectory/segments/CircleTests.kt | 2 +- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/gradle.properties b/gradle.properties index 16cdd3551..cc44b5b02 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.0-kotlin-1.8.10 +toolsVersion=0.14.1-kotlin-1.8.10 org.gradle.parallel=true diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index 945b140c2..d3165e162 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -5,10 +5,7 @@ package space.kscience.kmath.trajectory -import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.DoubleVector2D -import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.LineSegment +import space.kscience.kmath.geometry.* import kotlin.math.* /** @@ -18,10 +15,14 @@ import kotlin.math.* public fun Circle2D.tangentsToCircle( other: Circle2D, ): Map> = with(Euclidean2DSpace) { + //return empty map for concentric circles + if(center.equalsVector(other.center)) return@tangentsToCircle emptyMap() + + // A line connecting centers val line = LineSegment(center, other.center) - val d = line.begin.distanceTo(line.end) + // Distance between centers + val distance = line.begin.distanceTo(line.end) val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) - var r: Double var angle2: Double val routes = mapOf( DubinsPath.Type.RSR to Pair(radius, other.radius), @@ -33,30 +34,27 @@ public fun Circle2D.tangentsToCircle( for ((route, r1r2) in routes) { val r1 = r1r2.first val r2 = r1r2.second - r = if (r1.sign == r2.sign) { + val r = if (r1.sign == r2.sign) { r1.absoluteValue - r2.absoluteValue } else { r1.absoluteValue + r2.absoluteValue } - if (d * d > r * r) { - val l = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - route, - LineSegment( - center + w * r1, - other.center + w * r2 - ) + if (distance <= r) TODO("Intersecting circles are not supported yet") + val l = sqrt(distance * distance - r * r) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put( + route, + LineSegment( + center + w * r1, + other.center + w * r2 ) - } - else { - throw Exception("Circles should not be") - } + ) + } } } \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt index 3e87b47de..6d4493124 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt @@ -13,7 +13,6 @@ import space.kscience.kmath.geometry.equalsLine import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -import kotlin.test.assertFailsWith class TangentTest { @Test @@ -56,26 +55,23 @@ class TangentTest { } @Test - fun nonExistingTangents() { - assertFailsWith { - val c1 = Circle2D(vector(0.0, 0.0), 10.0) - val c2 = Circle2D(vector(0.0, 0.0), 1.0) - val segments = c1.tangentsToCircle(c2) - } - assertFailsWith { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(0.0, 0.0), 10.0) - val segments = c1.tangentsToCircle(c2) - } - assertFailsWith { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(2.0, 0.0), 1.0) - val segments = c1.tangentsToCircle(c2) - } - assertFailsWith { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(0.5, 0.0), 1.0) - val segments = c1.tangentsToCircle(c2) - } + fun concentric(){ + val c1 = Circle2D(vector(0.0, 0.0), 10.0) + val c2 = Circle2D(vector(0.0, 0.0), 1.0) + assertEquals(emptyMap(), c1.tangentsToCircle(c2)) } +// +// @Test +// fun nonExistingTangents() { +// assertFailsWith { +// val c1 = Circle2D(vector(0.0, 0.0), 1.0) +// val c2 = Circle2D(vector(2.0, 0.0), 1.0) +// c1.tangentsToCircle(c2) +// } +// assertFailsWith { +// val c1 = Circle2D(vector(0.0, 0.0), 1.0) +// val c2 = Circle2D(vector(0.5, 0.0), 1.0) +// c1.tangentsToCircle(c2) +// } +// } } \ No newline at end of file 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 index 27434b874..c3fca06ec 100644 --- 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 @@ -19,6 +19,6 @@ class CircleTests { val radius = 2.0 val expectedCircumference = 12.56637 val circle = Circle2D(center, radius) - assertEquals(expectedCircumference, circle.circumference) + assertEquals(expectedCircumference, circle.circumference, 1e-4) } } From db61f7144089056ae184fd1b28c1dd0db2c5fd6f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 18 Feb 2023 19:04:07 +0300 Subject: [PATCH 42/72] update build tools --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index cc44b5b02..c3f070c2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.1-kotlin-1.8.10 +toolsVersion=0.14.2-kotlin-1.8.10 org.gradle.parallel=true From 2c13386646a6f3f38523e9546eccf38343251163 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 1 Mar 2023 10:40:54 +0300 Subject: [PATCH 43/72] search for shortest path algorithm --- .../space/kscience/kmath/geometry/Line.kt | 1 + .../kmath/trajectory/DubinsObstacle.kt | 413 ++++++++++++++++++ .../kscience/kmath/trajectory/DubinsPath.kt | 110 +++++ .../kscience/kmath/trajectory/tangent.kt | 66 ++- 4 files changed, 583 insertions(+), 7 deletions(-) create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt 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 ab322ddca..e593150f1 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.geometry import kotlinx.serialization.Serializable +import space.kscience.kmath.operations.DoubleField.pow /** * A line formed by [base] vector of start and a [direction] vector. Direction vector is not necessarily normalized, diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt new file mode 100644 index 000000000..56aa88e4a --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -0,0 +1,413 @@ +/* + * Copyright 2018-2023 KMath 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.* +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Euclidean2DSpace.minus +import space.kscience.kmath.geometry.Euclidean2DSpace.plus +import space.kscience.kmath.geometry.Euclidean2DSpace.times +import space.kscience.kmath.geometry.Euclidean2DSpace.vector +import space.kscience.kmath.geometry.Euclidean2DSpace.norm +import space.kscience.kmath.operations.DoubleField.pow +import kotlin.math.* + +public fun LineSegment2D.length(): Double { + return ((end.y - begin.y).pow(2.0) + (end.x - begin.x).pow(2.0)).pow(0.5) +} +public class DubinsObstacle( + public val circles: List +) { + public val tangents: List = boundaryTangents().first + public val boundaryRoute: DubinsPath.Type = boundaryTangents().second + public val center: Vector2D = + vector(this.circles.sumOf{it.center.x} / this.circles.size, + this.circles.sumOf{it.center.y} / this.circles.size) + private fun boundaryTangents(): Pair, DubinsPath.Type> { + // outer tangents for a polygon circles can be either lsl or rsr + + fun Circle2D.dubinsTangentsToCircles( + other: Circle2D, + ): Map = with(Euclidean2DSpace) { + val line = LineSegment(center, other.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(radius, other.radius), + DubinsPath.Type.RSL to Pair(radius, -other.radius), + DubinsPath.Type.LSR to Pair(-radius, other.radius), + DubinsPath.Type.LSL to Pair(-radius, -other.radius) + ) + return buildMap { + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (d * d > r * r) { + val l = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put(route, DubinsTangent(Circle2D(center, radius), + other, + this@DubinsObstacle, + this@DubinsObstacle, + LineSegment2D( + center + w * r1, + other.center + w * r2 + ), + DubinsPath.toSimpleTypes(route)) + ) + } else { + throw Exception("Circles should not intersect") + } + } + } + } + val firstCircles = this.circles.slice(-this.circles.size..-1) + val secondCircles = this.circles.slice(-this.circles.size+1..0) + val lslTangents = firstCircles.zip(secondCircles) + {a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.LSL]!!} + val rsrTangents = firstCircles.zip(secondCircles) + {a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.RSR]!!} + val center = vector( + this.circles.sumOf { it.center.x } / this.circles.size, + this.circles.sumOf { it.center.y } / this.circles.size + ) + val lslToCenter = lslTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + + lslTangents.sumOf { it.lineSegment.end.distanceTo(center) } + val rsrToCenter = rsrTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + + rsrTangents.sumOf { it.lineSegment.end.distanceTo(center) } + return if (rsrToCenter >= lslToCenter) { + Pair(rsrTangents, DubinsPath.Type.RSR) + } else { + Pair(lslTangents, DubinsPath.Type.LSL) + } + } + + public fun nextTangent(circle: Circle2D, route: DubinsPath.Type): DubinsTangent { + if (route == this.boundaryRoute) { + for (i in this.circles.indices) { + if (this.circles[i] == circle) { + return this.tangents[i] + } + } + } + else { + for (i in this.circles.indices) { + if (this.circles[i] == circle) { + return DubinsTangent(this.circles[i], + this.circles[i-1], + this, + this, + LineSegment2D(this.tangents[i-1].lineSegment.end, + this.tangents[i-1].lineSegment.begin), + DubinsPath.toSimpleTypes(route)) + } + } + } + + error("next tangent not found") + } + + public fun equals(other: DubinsObstacle): Boolean { + return this.circles == other.circles + } +} + +public data class DubinsTangent(val startCircle: Circle2D, + val endCircle: Circle2D, + val startObstacle: DubinsObstacle, + val endObstacle: DubinsObstacle, + val lineSegment: LineSegment2D, + val route: PathTypes) + +public fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { + fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { + return v1.x * v2.y - v1.y * v2.x + } + if (crossProduct(other.begin - this.begin, other.end - this.begin).sign == + crossProduct(other.begin - this.end, other.end - this.end).sign) { + return false + } + if (crossProduct(this.begin - other.begin, this.end - other.begin).sign == + crossProduct(this.begin - other.end, this.end - other.end).sign) { + return false + } + return true +} + +public fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { + val a = (this.begin.x - this.end.x).pow(2.0) + (this.begin.y - this.end.y).pow(2.0) + val b = 2 * ((this.begin.x - this.end.x) * (this.end.x - circle.center.x) + + (this.begin.y - this.end.y) * (this.end.y - circle.center.y)) + val c = (this.end.x - circle.center.x).pow(2.0) + (this.end.y - circle.center.y) - + circle.radius.pow(2.0) + val d = b.pow(2.0) - 4 * a * c + if (d < 1e-6) { + return false + } + else { + val t1 = (-b - d.pow(0.5)) * 0.5 / a + val t2 = (-b + d.pow(0.5)) * 0.5 / a + if (((0 < t1) and (t1 < 1)) or ((0 < t2) and (t2 < 1))) { + return true + } + } + return false +} + +public fun DubinsTangent.intersectObstacle(obstacle: DubinsObstacle): Boolean { + for (tangent in obstacle.tangents) { + if (this.lineSegment.intersectSegment(tangent.lineSegment)) { + return true + } + } + for (circle in obstacle.circles) { + if (this.lineSegment.intersectCircle(circle)) { + return true + } + } + return false +} + +public fun outerTangents(first: DubinsObstacle, second: DubinsObstacle): MutableMap { + return buildMap { + for (circle1 in first.circles) { + for (circle2 in second.circles) { + for (tangent in dubinsTangentsToCircles(circle1, circle2, first, second)) { + if (!(tangent.value.intersectObstacle(first)) + and !(tangent.value.intersectObstacle(second))) { + put( + tangent.key, + tangent.value + ) + } + } + } + } + }.toMutableMap() +} + +public fun arcLength(circle: Circle2D, + point1: DoubleVector2D, + point2: DoubleVector2D, + route: DubinsPath.SimpleType): Double { + val phi1 = atan2(point1.y - circle.center.y, point1.x - circle.center.x) + val phi2 = atan2(point2.y - circle.center.y, point2.x - circle.center.x) + var angle = 0.0 + when (route) { + DubinsPath.SimpleType.L -> { + angle = if (phi2 >= phi1) { + phi2 - phi1 + } else { + 2 * PI + phi2 - phi1 + } + } + DubinsPath.SimpleType.R -> { + angle = if (phi2 >= phi1) { + 2 * PI - (phi2 - phi1) + } else { + -(phi2 - phi1) + } + } + DubinsPath.SimpleType.S -> { + error("L or R route is expected") + } + } + return circle.radius * angle +} + +public fun normalVectors(v: DoubleVector2D, r: Double): Pair { + return Pair( + r * vector(v.y / norm(v), -v.x / norm(v)), + r * vector(-v.y / norm(v), v.x / norm(v)) + ) +} + +public fun constructTangentCircles(point: DoubleVector2D, + direction: DoubleVector2D, + r: Double): Map { + val center1 = point + normalVectors(direction, r).first + val center2 = point + normalVectors(direction, r).second + val p1 = center1 - point + val p2 = center2 - point + return if (atan2(p1.y, p1.x) - atan2(p2.y, p2.x) in listOf(PI/2, -3*PI/2)) { + mapOf(DubinsPath.SimpleType.L to Circle2D(center1, r), + DubinsPath.SimpleType.R to Circle2D(center2, r)) + } + else { + mapOf(DubinsPath.SimpleType.L to Circle2D(center2, r), + DubinsPath.SimpleType.R to Circle2D(center1, r)) + } +} + +public fun sortedObstacles(currentObstacle: DubinsObstacle, + obstacles: List): List { + return obstacles.sortedBy {norm(it.center - currentObstacle.center)}.reversed() +} + +public fun tangentsAlongTheObstacle(initialCircle: Circle2D, + initialRoute: DubinsPath.Type, + finalCircle: Circle2D, + obstacle: DubinsObstacle): MutableList { + val dubinsTangents = mutableListOf() + var tangent = obstacle.nextTangent(initialCircle, initialRoute) + dubinsTangents.add(tangent) + while (tangent.endCircle != finalCircle) { + tangent = obstacle.nextTangent(tangent.endCircle, initialRoute) + dubinsTangents.add(tangent) + } + return dubinsTangents +} + +public fun allFinished(paths: List>, + finalObstacle: DubinsObstacle): Boolean { + for (path in paths) { + if (path[-1].endObstacle != finalObstacle) { + return false + } + } + return true +} + +public fun pathLength(path: List): Double { + val tangentsLength = path.sumOf{norm(it.lineSegment.end - it.lineSegment.begin)} + val arcsLength = buildList{ + for (i in 1..path.size) { + add(arcLength(path[i].startCircle, + path[i-1].lineSegment.end, + path[i].lineSegment.begin, + path[i].route[0])) + } + }.sum() + return tangentsLength + arcsLength +} + +public fun shortestPath(path: List>): List> { + return path.sortedBy { pathLength(it) } +} + +public typealias Path = List +public fun findAllPaths( + startingPoint: DoubleVector2D, + startingDirection: DoubleVector2D, + startingRadius: Double, + finalPoint: DoubleVector2D, + finalDirection: DoubleVector2D, + finalRadius: Double, + obstacles: List +) { + val initialCircles = constructTangentCircles( + startingPoint, + startingDirection, + startingRadius) + val finalCircles = constructTangentCircles( + finalPoint, + finalDirection, + finalRadius) + var outputTangents = mutableMapOf>() + for (i in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { + for (j in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { + val finalCircle = finalCircles[j]!! + val finalObstacle = DubinsObstacle(listOf(finalCircle)) + outputTangents[listOf(i, + DubinsPath.SimpleType.S, + j)] = listOf( + listOf(DubinsTangent( + initialCircles[i]!!, + initialCircles[i]!!, + DubinsObstacle(listOf(initialCircles[i]!!)), + DubinsObstacle(listOf(initialCircles[i]!!)), + LineSegment2D(startingPoint, startingPoint), + listOf(i, DubinsPath.SimpleType.S, i) + ))) + var currentObstacle = DubinsObstacle(listOf(initialCircles[i]!!)) + while (!allFinished(outputTangents[listOf(i, + DubinsPath.SimpleType.S, + j)]!!, finalObstacle)) { + var newOutputTangents = listOf() + for (line in outputTangents[listOf(i, + DubinsPath.SimpleType.S, + j)]!!) { + var currentCircle = line[-1].endCircle + var currentDirection = line[-1].route[-1] + var currentObstacle = line[-1].endObstacle + var nextObstacle = DubinsObstacle(listOf()) + if (currentObstacle != finalObstacle) { + var tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.toType(listOf( + currentDirection, + DubinsPath.SimpleType.S, + j) + )] + for (obstacle in sortedObstacles(currentObstacle, obstacles)) { + if (tangentToFinal!!.intersectObstacle(obstacle)) { + nextObstacle = obstacle + break + } + } + if (nextObstacle == DubinsObstacle(listOf())) { + nextObstacle = finalObstacle + } + var nextTangents = outerTangents(currentObstacle, nextObstacle) +// for (pathType in listOf( +// listOf(DubinsPath.SimpleType.L, +// DubinsPath.SimpleType.S, +// DubinsPath.SimpleType.L), +// listOf(DubinsPath.SimpleType.L, +// DubinsPath.SimpleType.S, +// DubinsPath.SimpleType.R), +// listOf(DubinsPath.SimpleType.R, +// DubinsPath.SimpleType.S, +// DubinsPath.SimpleType.L), +// listOf(DubinsPath.SimpleType.R, +// DubinsPath.SimpleType.S, +// DubinsPath.SimpleType.R) +// )) { + for (pathType in nextTangents.keys) { + for (obstacle in obstacles) { + // in Python code here try/except was used, but seems unneeded + if (nextTangents[pathType]!!.intersectObstacle(obstacle)) { + nextTangents.remove(pathType) + } + + } + } + if (nextObstacle == finalObstacle) { + nextTangents = + nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection) and + (DubinsPath.toSimpleTypes(it.key)[0] == j)} + as MutableMap + } + else { + nextTangents = + nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} + as MutableMap + } + TODO("rewrite fragment from Python") + } + } + } + } + } +} + + + + + + + + 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 index 568ef691a..5654d10ae 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -77,10 +77,118 @@ private fun innerTangent( @Suppress("DuplicatedCode") public object DubinsPath { +// public class ArcType(private val type: Type){ +// public val first: SimpleType +// get() { +// if (this.type in listOf(Type.RSR, Type.RSL, Type.RLR)) { +// return SimpleType.R +// } +// else if (type in listOf(Type.LSL, Type.LSR, Type.LRL)) { +// return SimpleType.L +// } +// error("Wrong DubinsPath.Type") +// } +// +// public val last: SimpleType +// get() { +// if (type in listOf(Type.RSR, Type.LSR, Type.RLR)) { +// return SimpleType.R +// } +// else if (type in listOf(Type.LSL, Type.RSL, Type.LRL)) { +// return SimpleType.L +// } +// error("Wrong DubinsPath.Type") +// } +// public val intermediate: SimpleType +// get() { +// if (type == Type.RLR) { +// return SimpleType.L +// } +// else if (type == Type.LRL) { +// return SimpleType.R +// } +// error("This DubinsPath.Type doesn't contain intermediate arc") +// } +// } + + public enum class SimpleType { + R, S, L + } + public enum class Type { RLR, LRL, RSR, LSL, RSL, LSR } + public fun toSimpleTypes(type: Type): List { + when (type) { + Type.RLR -> { + return listOf(SimpleType.R, SimpleType.L, SimpleType.R) + } + Type.LRL -> { + return listOf(SimpleType.L, SimpleType.R, SimpleType.L) + } + Type.RSR -> { + return listOf(SimpleType.R, SimpleType.S, SimpleType.R) + } + Type.LSL -> { + return listOf(SimpleType.L, SimpleType.S, SimpleType.L) + } + Type.RSL -> { + return listOf(SimpleType.R, SimpleType.S, SimpleType.L) + } + Type.LSR -> { + return listOf(SimpleType.L, SimpleType.S, SimpleType.R) + } + else -> error("This type doesn't exist") + } + } + + public fun toType(types: List): Type { + when (types) { + listOf(SimpleType.R, SimpleType.L, SimpleType.R) -> { + return Type.RLR + } + listOf(SimpleType.L, SimpleType.R, SimpleType.L) -> { + return Type.LRL + } + listOf(SimpleType.R, SimpleType.S, SimpleType.R) -> { + return Type.RSR + } + listOf(SimpleType.L, SimpleType.S, SimpleType.L) -> { + return Type.LSL + } + listOf(SimpleType.R, SimpleType.S, SimpleType.L) -> { + return Type.RSL + } + listOf(SimpleType.L, SimpleType.S, SimpleType.R) -> { + return Type.LSR + } + else -> error("This type doesn't exist") + } + } + +// public class PathTypes(private val inputTypes: List) { +// public val type: Type +// get() { +// when (this.inputTypes) { +// listOf(SimpleType.R, SimpleType.S, SimpleType.R) -> { +// return Type.RSR +// } +// listOf(SimpleType.R, SimpleType.S, SimpleType.L) -> { +// return Type.RSL +// } +// listOf(SimpleType.L, SimpleType.S, SimpleType.R) -> { +// return Type.LSR +// } +// listOf(SimpleType.L, SimpleType.S, SimpleType.L) -> { +// return Type.LSL +// } +// else -> error("Wrong list of SimpleTypes") +// } +// } +// public val chain: List = this.inputTypes +// } + /** * Return Dubins trajectory type or null if trajectory is not a Dubins path */ @@ -243,6 +351,8 @@ public object DubinsPath { } } +public typealias PathTypes = List + public fun interface MaxCurvature { public fun compute(startPoint: PhaseVector2D): Double } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index 945b140c2..2d935aa00 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.trajectory -import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.DoubleVector2D -import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.LineSegment +import space.kscience.kmath.geometry.* +import space.kscience.kmath.geometry.Euclidean2DSpace.plus +import space.kscience.kmath.geometry.Euclidean2DSpace.times +import space.kscience.kmath.operations.DoubleField.pow import kotlin.math.* /** @@ -17,7 +17,7 @@ import kotlin.math.* */ public fun Circle2D.tangentsToCircle( other: Circle2D, -): Map> = with(Euclidean2DSpace) { +): Map = with(Euclidean2DSpace) { val line = LineSegment(center, other.center) val d = line.begin.distanceTo(line.end) val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) @@ -48,14 +48,66 @@ public fun Circle2D.tangentsToCircle( val w = vector(-cos(angle2), sin(angle2)) put( route, - LineSegment( + LineSegment2D( center + w * r1, other.center + w * r2 ) ) } else { - throw Exception("Circles should not be") + throw Exception("Circles should not intersect") + } + } + } +} + +public fun dubinsTangentsToCircles( + firstCircle: Circle2D, + secondCircle: Circle2D, + firstObstacle: DubinsObstacle, + secondObstacle: DubinsObstacle +): Map = with(Euclidean2DSpace) { + val line = LineSegment(firstCircle.center, secondCircle.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(secondCircle.center.x - firstCircle.center.x, + secondCircle.center.y - firstCircle.center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(firstCircle.radius, secondCircle.radius), + DubinsPath.Type.RSL to Pair(firstCircle.radius, -secondCircle.radius), + DubinsPath.Type.LSR to Pair(-firstCircle.radius, secondCircle.radius), + DubinsPath.Type.LSL to Pair(-firstCircle.radius, -secondCircle.radius) + ) + return buildMap { + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (d * d > r * r) { + val l = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + put(route, DubinsTangent(Circle2D(firstCircle.center, firstCircle.radius), + secondCircle, + firstObstacle, + secondObstacle, + LineSegment2D( + firstCircle.center + w * r1, + secondCircle.center + w * r2 + ), + DubinsPath.toSimpleTypes(route)) + ) + } else { + throw Exception("Circles should not intersect") } } } From 61d43ae5faa05f8c9d90d6519897a7f0ebd6b77a Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Sat, 4 Mar 2023 21:31:06 +0300 Subject: [PATCH 44/72] search for shortest path algorithm --- .../kmath/trajectory/DubinsObstacle.kt | 144 ++++++++++++++---- .../kscience/kmath/trajectory/tangent.kt | 82 ++++++++-- .../kscience/kmath/trajectory/DubinsTest.kt | 39 +++++ 3 files changed, 225 insertions(+), 40 deletions(-) create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index 56aa88e4a..e1c967e2a 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -276,7 +276,7 @@ public fun tangentsAlongTheObstacle(initialCircle: Circle2D, public fun allFinished(paths: List>, finalObstacle: DubinsObstacle): Boolean { for (path in paths) { - if (path[-1].endObstacle != finalObstacle) { + if (path.last().endObstacle != finalObstacle) { return false } } @@ -296,8 +296,8 @@ public fun pathLength(path: List): Double { return tangentsLength + arcsLength } -public fun shortestPath(path: List>): List> { - return path.sortedBy { pathLength(it) } +public fun shortestPath(path: List>): List { + return path.sortedBy { pathLength(it) }[0] } public typealias Path = List @@ -309,7 +309,7 @@ public fun findAllPaths( finalDirection: DoubleVector2D, finalRadius: Double, obstacles: List -) { +): List> { val initialCircles = constructTangentCircles( startingPoint, startingDirection, @@ -318,15 +318,15 @@ public fun findAllPaths( finalPoint, finalDirection, finalRadius) - var outputTangents = mutableMapOf>() + var outputTangents = mutableMapOf>>() for (i in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { for (j in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { val finalCircle = finalCircles[j]!! val finalObstacle = DubinsObstacle(listOf(finalCircle)) outputTangents[listOf(i, DubinsPath.SimpleType.S, - j)] = listOf( - listOf(DubinsTangent( + j)] = mutableListOf( + mutableListOf(DubinsTangent( initialCircles[i]!!, initialCircles[i]!!, DubinsObstacle(listOf(initialCircles[i]!!)), @@ -338,13 +338,13 @@ public fun findAllPaths( while (!allFinished(outputTangents[listOf(i, DubinsPath.SimpleType.S, j)]!!, finalObstacle)) { - var newOutputTangents = listOf() + var newOutputTangents = mutableListOf>() for (line in outputTangents[listOf(i, DubinsPath.SimpleType.S, j)]!!) { - var currentCircle = line[-1].endCircle - var currentDirection = line[-1].route[-1] - var currentObstacle = line[-1].endObstacle + var currentCircle = line.last().endCircle + var currentDirection = line.last().route.last() + var currentObstacle = line.last().endObstacle var nextObstacle = DubinsObstacle(listOf()) if (currentObstacle != finalObstacle) { var tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.toType(listOf( @@ -362,20 +362,7 @@ public fun findAllPaths( nextObstacle = finalObstacle } var nextTangents = outerTangents(currentObstacle, nextObstacle) -// for (pathType in listOf( -// listOf(DubinsPath.SimpleType.L, -// DubinsPath.SimpleType.S, -// DubinsPath.SimpleType.L), -// listOf(DubinsPath.SimpleType.L, -// DubinsPath.SimpleType.S, -// DubinsPath.SimpleType.R), -// listOf(DubinsPath.SimpleType.R, -// DubinsPath.SimpleType.S, -// DubinsPath.SimpleType.L), -// listOf(DubinsPath.SimpleType.R, -// DubinsPath.SimpleType.S, -// DubinsPath.SimpleType.R) -// )) { + for (pathType in nextTangents.keys) { for (obstacle in obstacles) { // in Python code here try/except was used, but seems unneeded @@ -396,12 +383,117 @@ public fun findAllPaths( nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} as MutableMap } - TODO("rewrite fragment from Python") + val tangentsAlong = mutableListOf() + for (tangent in nextTangents.values) { + if (tangent.startCircle == line.last().endCircle) { + val lengthMaxPossible = arcLength( + tangent.startCircle, + line.last().lineSegment.end, + tangent.startObstacle.nextTangent( + tangent.startCircle, + DubinsPath.toType(listOf(currentDirection, DubinsPath.SimpleType.S, currentDirection)), + ).lineSegment.begin, + currentDirection + ) + val lengthCalculated = arcLength( + tangent.startCircle, + line.last().lineSegment.end, + tangent.lineSegment.begin, + currentDirection) + if (lengthCalculated > lengthMaxPossible) { + val tangentsAlong = tangentsAlongTheObstacle( + currentCircle, + DubinsPath.toType(listOf( + currentDirection, + DubinsPath.SimpleType.S, + currentDirection)), + tangent.startCircle, + currentObstacle + ) + } + else { + val tangentsAlong = mutableListOf() + } + } + else { + val tangentsAlong = tangentsAlongTheObstacle( + currentCircle, + DubinsPath.toType(listOf( + currentDirection, + DubinsPath.SimpleType.S, + currentDirection)), + tangent.startCircle, + currentObstacle + ) + } + newOutputTangents.add((line + tangentsAlong + listOf(tangent)).toMutableList()) + } + outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )] = newOutputTangents + } + else { + // minor changes from Python code + newOutputTangents.add(line) + outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )] = newOutputTangents } } } + for (lineId in outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )]!!.indices) { + val lastDirection = outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )]!![lineId].last().route[2] + outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )]!![lineId].add(DubinsTangent( + finalCircles[j]!!, + finalCircles[j]!!, + DubinsObstacle( + listOf(finalCircles[j]!!) + ), + DubinsObstacle( + listOf(finalCircles[j]!!) + ), + LineSegment2D(finalPoint, finalPoint), + listOf( + lastDirection, + DubinsPath.SimpleType.S, + j + ) + )) + } } } + return outputTangents[listOf( + DubinsPath.SimpleType.L, + DubinsPath.SimpleType.S, + DubinsPath.SimpleType.L + )]!! + outputTangents[listOf( + DubinsPath.SimpleType.L, + DubinsPath.SimpleType.S, + DubinsPath.SimpleType.R + )]!! + outputTangents[listOf( + DubinsPath.SimpleType.R, + DubinsPath.SimpleType.S, + DubinsPath.SimpleType.L + )]!! + outputTangents[listOf( + DubinsPath.SimpleType.R, + DubinsPath.SimpleType.S, + DubinsPath.SimpleType.L)]!! } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index d3165e162..1a58d64cc 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -39,22 +39,76 @@ public fun Circle2D.tangentsToCircle( } else { r1.absoluteValue + r2.absoluteValue } - if (distance <= r) TODO("Intersecting circles are not supported yet") - val l = sqrt(distance * distance - r * r) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - route, - LineSegment( - center + w * r1, - other.center + w * r2 + if (distance * distance >= r * r) { + val l = sqrt(distance * distance - r * r) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + put( + route, + LineSegment( + center + w * r1, + other.center + w * r2 + ) ) - ) + } else { + throw Exception("Circles should not intersect") + } + } + } +} +public fun dubinsTangentsToCircles( + firstCircle: Circle2D, + secondCircle: Circle2D, + firstObstacle: DubinsObstacle, + secondObstacle: DubinsObstacle +): Map = with(Euclidean2DSpace) { + val line = LineSegment(firstCircle.center, secondCircle.center) + val distance = line.begin.distanceTo(line.end) + val angle1 = atan2(secondCircle.center.x - firstCircle.center.x, + secondCircle.center.y - firstCircle.center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(firstCircle.radius, secondCircle.radius), + DubinsPath.Type.RSL to Pair(firstCircle.radius, -secondCircle.radius), + DubinsPath.Type.LSR to Pair(-firstCircle.radius, secondCircle.radius), + DubinsPath.Type.LSL to Pair(-firstCircle.radius, -secondCircle.radius) + ) + return buildMap { + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (distance * distance >= r * r) { + val l = sqrt(distance * distance - r * r) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + put(route, DubinsTangent(Circle2D(firstCircle.center, firstCircle.radius), + secondCircle, + firstObstacle, + secondObstacle, + LineSegment2D( + firstCircle.center + w * r1, + secondCircle.center + w * r2 + ), + DubinsPath.toSimpleTypes(route)) + ) + } else { + throw Exception("Circles should not intersect") + } } } } \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt new file mode 100644 index 000000000..3eefbdaeb --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2018-2023 KMath 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.vector +import kotlin.test.Test +import kotlin.test.assertTrue + +class DubinsTest { + @Test + fun firstPath() { + val startPoint = vector(-5.0, -1.0) + val startDirection = vector(1.0, 1.0) + val startRadius = 0.5 + val finalPoint = vector(20.0, 4.0) + val finalDirection = vector(1.0, -1.0) + val finalRadius = 0.5 + + val obstacles = listOf(DubinsObstacle(listOf( + Circle2D(vector(7.0, 1.0), 5.0)))) + + val outputTangents = findAllPaths( + startPoint, + startDirection, + startRadius, + finalPoint, + finalDirection, + finalRadius, + obstacles) + val length = pathLength(shortestPath(outputTangents)) + TODO("fix negative indices in boundaryTangents and accomplish test") + assertTrue(false) + } +} \ No newline at end of file From 1b6a41c728150bb9374625b06045c06f8073c524 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 9 Mar 2023 08:39:20 +0300 Subject: [PATCH 45/72] search for shortest path algorithm --- .../kmath/trajectory/DubinsObstacle.kt | 30 ++++++++--------- .../kscience/kmath/trajectory/tangent.kt | 2 +- .../kscience/kmath/trajectory/DubinsTest.kt | 33 +++++++++++++++++++ 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index e1c967e2a..d3ab13f26 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -39,8 +39,8 @@ public class DubinsObstacle( var angle2: Double val routes = mapOf( DubinsPath.Type.RSR to Pair(radius, other.radius), - DubinsPath.Type.RSL to Pair(radius, -other.radius), - DubinsPath.Type.LSR to Pair(-radius, other.radius), +// DubinsPath.Type.RSL to Pair(radius, -other.radius), +// DubinsPath.Type.LSR to Pair(-radius, other.radius), DubinsPath.Type.LSL to Pair(-radius, -other.radius) ) return buildMap { @@ -52,7 +52,7 @@ public class DubinsObstacle( } else { r1.absoluteValue + r2.absoluteValue } - if (d * d > r * r) { + if (d * d >= r * r) { val l = (d * d - r * r).pow(0.5) angle2 = if (r1.absoluteValue > r2.absoluteValue) { angle1 + r1.sign * atan2(r.absoluteValue, l) @@ -76,8 +76,11 @@ public class DubinsObstacle( } } } - val firstCircles = this.circles.slice(-this.circles.size..-1) - val secondCircles = this.circles.slice(-this.circles.size+1..0) +// val firstCircles = this.circles.slice(-this.circles.size..-1) +// val secondCircles = this.circles.slice(-this.circles.size+1..0) + val firstCircles = this.circles + val secondCircles = this.circles.slice(1..this.circles.lastIndex) + + this.circles[0] val lslTangents = firstCircles.zip(secondCircles) {a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.LSL]!!} val rsrTangents = firstCircles.zip(secondCircles) @@ -345,7 +348,7 @@ public fun findAllPaths( var currentCircle = line.last().endCircle var currentDirection = line.last().route.last() var currentObstacle = line.last().endObstacle - var nextObstacle = DubinsObstacle(listOf()) + var nextObstacle: DubinsObstacle? = null if (currentObstacle != finalObstacle) { var tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.toType(listOf( currentDirection, @@ -358,7 +361,7 @@ public fun findAllPaths( break } } - if (nextObstacle == DubinsObstacle(listOf())) { + if (nextObstacle == null) { nextObstacle = finalObstacle } var nextTangents = outerTangents(currentObstacle, nextObstacle) @@ -372,16 +375,13 @@ public fun findAllPaths( } } - if (nextObstacle == finalObstacle) { - nextTangents = - nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection) and + nextTangents = if (nextObstacle == finalObstacle) { + nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection) and (DubinsPath.toSimpleTypes(it.key)[0] == j)} as MutableMap - } - else { - nextTangents = - nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} - as MutableMap + } else { + nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} + as MutableMap } val tangentsAlong = mutableListOf() for (tangent in nextTangents.values) { diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt index 1a58d64cc..fb1c3927b 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt @@ -95,7 +95,7 @@ public fun dubinsTangentsToCircles( } else { angle1 - r2.sign * atan2(r.absoluteValue, l) } - val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + val w = vector(-cos(angle2), sin(angle2)) put(route, DubinsTangent(Circle2D(firstCircle.center, firstCircle.radius), secondCircle, firstObstacle, diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index 3eefbdaeb..a0697c59c 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -36,4 +36,37 @@ class DubinsTest { TODO("fix negative indices in boundaryTangents and accomplish test") assertTrue(false) } + @Test + fun outerTangentsTest1() { + // works incorrectly + val circles1 = listOf( + Circle2D(vector(0.0, 0.0), 1.0)) + val circles2 = listOf( + Circle2D(vector(5.0, 5.0), 1.0) + ) + println(outerTangents(DubinsObstacle(circles1), DubinsObstacle(circles2))) + assertTrue(false) + } + @Test + fun outerTangentsTest2() { + // works incorrectly + val circles1 = listOf( + Circle2D(vector(0.0, 0.0), 1.0), + Circle2D(vector( 2.0, 0.0), 1.0)) + val circles2 = listOf( + Circle2D(vector(5.0, 5.0), 1.0), + Circle2D(vector(7.0, 5.0), 1.0) + ) + println(outerTangents(DubinsObstacle(circles1), DubinsObstacle(circles2))) + + for (circle1 in circles1) { + for (circle2 in circles2) { + for (tangent in dubinsTangentsToCircles(circle1, circle2, + DubinsObstacle(circles1), DubinsObstacle(circles2))) { + println(tangent) + } + } + } + assertTrue(false) + } } \ No newline at end of file From 2bce369c5dcdae8b4ba16f498fd19d31807b29df Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 9 Mar 2023 16:03:48 +0300 Subject: [PATCH 46/72] search for shortest path algorithm --- .../kmath/trajectory/DubinsObstacle.kt | 38 ++++++++++++------- .../kscience/kmath/trajectory/DubinsTest.kt | 37 +++++++++++++++++- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index d3ab13f26..6b247e55b 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -111,13 +111,24 @@ public class DubinsObstacle( else { for (i in this.circles.indices) { if (this.circles[i] == circle) { - return DubinsTangent(this.circles[i], - this.circles[i-1], - this, - this, - LineSegment2D(this.tangents[i-1].lineSegment.end, - this.tangents[i-1].lineSegment.begin), - DubinsPath.toSimpleTypes(route)) + if (i > 0) { + return DubinsTangent(this.circles[i], + this.circles[i-1], + this, + this, + LineSegment2D(this.tangents[i-1].lineSegment.end, + this.tangents[i-1].lineSegment.begin), + DubinsPath.toSimpleTypes(route)) + } + else { + return DubinsTangent(this.circles[0], + this.circles.last(), + this, + this, + LineSegment2D(this.tangents.last().lineSegment.end, + this.tangents.last().lineSegment.begin), + DubinsPath.toSimpleTypes(route)) + } } } } @@ -156,7 +167,7 @@ public fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { val a = (this.begin.x - this.end.x).pow(2.0) + (this.begin.y - this.end.y).pow(2.0) val b = 2 * ((this.begin.x - this.end.x) * (this.end.x - circle.center.x) + (this.begin.y - this.end.y) * (this.end.y - circle.center.y)) - val c = (this.end.x - circle.center.x).pow(2.0) + (this.end.y - circle.center.y) - + val c = (this.end.x - circle.center.x).pow(2.0) + (this.end.y - circle.center.y).pow(2.0) - circle.radius.pow(2.0) val d = b.pow(2.0) - 4 * a * c if (d < 1e-6) { @@ -289,7 +300,7 @@ public fun allFinished(paths: List>, public fun pathLength(path: List): Double { val tangentsLength = path.sumOf{norm(it.lineSegment.end - it.lineSegment.begin)} val arcsLength = buildList{ - for (i in 1..path.size) { + for (i in 1..path.lastIndex) { add(arcLength(path[i].startCircle, path[i-1].lineSegment.end, path[i].lineSegment.begin, @@ -366,13 +377,14 @@ public fun findAllPaths( } var nextTangents = outerTangents(currentObstacle, nextObstacle) - for (pathType in nextTangents.keys) { + for (pathType in DubinsPath.Type.values()) { for (obstacle in obstacles) { // in Python code here try/except was used, but seems unneeded - if (nextTangents[pathType]!!.intersectObstacle(obstacle)) { - nextTangents.remove(pathType) + if (nextTangents.containsKey(pathType)) { + if (nextTangents[pathType]!!.intersectObstacle(obstacle)) { + nextTangents.remove(pathType) + } } - } } nextTangents = if (nextObstacle == finalObstacle) { diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index a0697c59c..16d77c84d 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -33,8 +33,41 @@ class DubinsTest { finalRadius, obstacles) val length = pathLength(shortestPath(outputTangents)) - TODO("fix negative indices in boundaryTangents and accomplish test") - assertTrue(false) + println(length) + } + + @Test + fun secondPath() { + val startPoint = vector(-5.0, -1.0) + val startDirection = vector(1.0, 1.0) + val startRadius = 0.5 + val finalPoint = vector(20.0, 4.0) + val finalDirection = vector(1.0, -1.0) + val finalRadius = 0.5 + + val obstacles = listOf( + DubinsObstacle(listOf( + Circle2D(vector(1.0, 6.5), 0.5), + Circle2D(vector(2.0, 1.0), 0.5), + Circle2D(vector(6.0, 0.0), 0.5), + Circle2D(vector(5.0, 5.0), 0.5) + )), DubinsObstacle(listOf( + Circle2D(vector(10.0, 1.0), 0.5), + Circle2D(vector(16.0, 0.0), 0.5), + Circle2D(vector(14.0, 6.0), 0.5), + Circle2D(vector(9.0, 4.0), 0.5) + )) + ) + val outputTangents = findAllPaths( + startPoint, + startDirection, + startRadius, + finalPoint, + finalDirection, + finalRadius, + obstacles) + val length = pathLength(shortestPath(outputTangents)) + println(length) } @Test fun outerTangentsTest1() { From 4871baf0e5f4d45bf3c7d31916d4b84be187b689 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 12:01:08 +0300 Subject: [PATCH 47/72] Add vector product to Euclidean3DSpace --- gradle.properties | 2 +- .../kmath/geometry/Euclidean3DSpace.kt | 47 ++++++++++++++++++- .../kmath/geometry/Euclidean3DSpaceTest.kt | 46 ++++++++++++------ 3 files changed, 78 insertions(+), 17 deletions(-) diff --git a/gradle.properties b/gradle.properties index c3f070c2d..048c9c9f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.2-kotlin-1.8.10 +toolsVersion=0.14.3-kotlin-1.8.20-RC org.gradle.parallel=true 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 cc641a3f1..f1cf0bad2 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 @@ -78,8 +78,11 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< } } + public fun vector(x: Double, y: Double, z: Double): DoubleVector3D = + Vector3DImpl(x, y, z) + public fun vector(x: Number, y: Number, z: Number): DoubleVector3D = - Vector3DImpl(x.toDouble(), y.toDouble(), z.toDouble()) + vector(x.toDouble(), y.toDouble(), z.toDouble()) override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) } @@ -100,6 +103,48 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< override fun DoubleVector3D.dot(other: DoubleVector3D): Double = x * other.x + y * other.y + z * other.z + private fun leviCivita(i: Int, j: Int, k: Int): Int = when { + // even permutation + i == 0 && j == 1 && k == 2 -> 1 + i == 1 && j == 2 && k == 0 -> 1 + i == 2 && j == 0 && k == 1 -> 1 + // odd permutations + i == 2 && j == 1 && k == 0 -> -1 + i == 0 && j == 2 && k == 1 -> -1 + i == 1 && j == 0 && k == 2 -> -1 + + else -> 0 + } + + /** + * Compute vector product of [first] and [second]. The basis assumed to be right-handed if [rightBasis] is true and + * left-handed otherwise + */ + public fun vectorProduct( + first: DoubleVector3D, + second: DoubleVector3D, + rightBasis: Boolean = true, + ): DoubleVector3D { + var x = 0.0 + var y = 0.0 + var z = 0.0 + + for (j in (0..2)) { + for (k in (0..2)) { + x += leviCivita(0, j, k) * first[j] * second[k] + y += leviCivita(1, j, k) * first[j] * second[k] + z += leviCivita(2, j, k) * first[j] * second[k] + } + } + + return vector(x, y, z) * (if (rightBasis) 1 else -1) + } + + /** + * Vector product with right basis + */ + public infix fun DoubleVector3D.cross(other: DoubleVector3D): Vector3D = vectorProduct(this, other) + 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/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt index 6d9a169eb..291b0ad47 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 @@ -57,23 +57,39 @@ internal class Euclidean3DSpaceTest { } @Test - fun add() { - with(Euclidean3DSpace) { - assertVectorEquals( - vector(1.0, -2.0, 0.001), - vector(1.0, -2.0, 0.001) + zero - ) - assertVectorEquals( - vector(8.0, -3.0, 3.001), - vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001) - ) - } + fun add() = with(Euclidean3DSpace) { + assertVectorEquals( + vector(1.0, -2.0, 0.001), + vector(1.0, -2.0, 0.001) + zero + ) + assertVectorEquals( + vector(8.0, -3.0, 3.001), + vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001) + ) } @Test - fun multiply() { - with(Euclidean3DSpace) { - assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2) - } + fun multiply() = with(Euclidean3DSpace) { + assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2) } + + @Test + fun vectorProduct() = with(Euclidean3DSpace) { + assertVectorEquals(zAxis, vectorProduct(xAxis, yAxis)) + assertVectorEquals(zAxis, xAxis cross yAxis) + assertVectorEquals(-zAxis, vectorProduct(yAxis, xAxis)) + assertVectorEquals(zAxis, vectorProduct(yAxis, xAxis, rightBasis = false)) + } + + @Test + fun doubleVectorProduct() = with(Euclidean3DSpace) { + val a = vector(1, 2, -3) + val b = vector(-1, 0, 1) + val c = vector(4, 5, 6) + + val res = a cross (b cross c) + val expected = b * (a dot c) - c * (a dot b) + assertVectorEquals(expected, res) + } + } From a3963ac4f50b7042cf21c51c8b5f97c36877249e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 21:40:14 +0300 Subject: [PATCH 48/72] Refactor series naming and docs --- .../kscience/kmath/series/SeriesAlgebra.kt | 79 +++++++++++-------- .../kscience/kmath/series/seriesExtensions.kt | 32 ++++---- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 3cd2212f6..45e392693 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -6,6 +6,7 @@ import space.kscience.kmath.operations.RingOps import space.kscience.kmath.stat.StatisticalAlgebra import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferView +import space.kscience.kmath.structures.getOrNull import kotlin.math.max import kotlin.math.min @@ -33,8 +34,6 @@ public interface Series : Buffer { public val position: Int } -public val Series.absoluteIndices: IntRange get() = position until position + size - /** * A [BufferView] with index offset (both positive and negative) and possible size change */ @@ -60,54 +59,68 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( private val labelResolver: (Int) -> L, ) : RingOps>, StatisticalAlgebra { - public val Buffer.indices: IntRange + /** + * A range of valid offset indices. In general, does not start with zero. + */ + public val Buffer.offsetIndices: IntRange get() = if (this is Series) { - absoluteIndices + position until position + size } else { 0 until size } /** - * Get the value by absolute index in the series algebra or return null if index is out of range + * Get the value by absolute offset in the series algebra or return null if index is out of range */ - public fun Buffer.getAbsoluteOrNull(index: Int): T? = when { - index !in indices -> null - this is Series -> origin[index - position] - else -> get(index) + public fun Buffer.getByOffsetOrNull(index: Int): T? = when { + index !in offsetIndices -> null + this is Series -> origin.getOrNull(index - position) + else -> getOrNull(index) } /** * Get the value by absolute index in the series algebra or throw [IndexOutOfBoundsException] if index is out of range */ - public fun Buffer.getAbsolute(index: Int): T = - getAbsoluteOrNull(index) ?: throw IndexOutOfBoundsException("Index $index is not in $indices") + public fun Buffer.getByOffset(index: Int): T = + getByOffsetOrNull(index) ?: throw IndexOutOfBoundsException("Index $index is not in $offsetIndices") /** - * Create an offset series with index starting point at [index] + * Zero-copy move [Buffer] or [Series] to given [position] ignoring series offset if it is present. */ - public fun Buffer.moveTo(index: Int): Series = if (this is Series) { - SeriesImpl(origin, index, size) + public fun Buffer.moveTo(position: Int): Series = if (this is Series) { + SeriesImpl(origin, position, size) } else { - SeriesImpl(this, index, size) + SeriesImpl(this, position, size) } - public val Buffer.offset: Int get() = if (this is Series) position else 0 + /** + * Zero-copy move [Buffer] or [Series] by given [offset]. If it is [Series], sum intrinsic series position and the [offset]. + */ + public fun Buffer.moveBy(offset: Int): Series = if (this is Series) { + SeriesImpl(origin, position + offset, size) + } else { + SeriesImpl(this, offset, size) + } /** - * Build a new series + * An offset of the buffer start relative to [SeriesAlgebra] zero offset */ - public fun series(size: Int, fromIndex: Int = 0, block: A.(label: L) -> T): Series { + public val Buffer.startOffset: Int get() = if (this is Series) position else 0 + + /** + * Build a new series positioned at [startOffset]. + */ + public fun series(size: Int, startOffset: Int = 0, block: A.(label: L) -> T): Series { return elementAlgebra.bufferFactory(size) { - val index = it + fromIndex + val index = it + startOffset elementAlgebra.block(labelResolver(index)) - }.moveTo(fromIndex) + }.moveTo(startOffset) } /** * Get a label buffer for given buffer. */ - public val Buffer.labels: List get() = indices.map(labelResolver) - + public val Buffer.labels: List get() = offsetIndices.map(labelResolver) /** * Try to resolve element by label and return null if element with a given label is not found @@ -115,7 +128,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( public operator fun Buffer.get(label: L): T? { val index = labels.indexOf(label) if (index == -1) return null - return getAbsolute(index + offset) + return getByOffset(index + startOffset) } /** @@ -123,9 +136,9 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( */ public inline fun Buffer.map(crossinline transform: A.(T) -> T): Series { val buf = elementAlgebra.bufferFactory(size) { - elementAlgebra.transform(getAbsolute(it)) + elementAlgebra.transform(getByOffset(it)) } - return buf.moveTo(indices.first) + return buf.moveTo(offsetIndices.first) } /** @@ -134,22 +147,22 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( public inline fun Buffer.mapWithLabel(crossinline transform: A.(arg: T, label: L) -> T): Series { val labels = labels val buf = elementAlgebra.bufferFactory(size) { - elementAlgebra.transform(getAbsolute(it), labels[it]) + elementAlgebra.transform(getByOffset(it), labels[it]) } - return buf.moveTo(indices.first) + return buf.moveTo(offsetIndices.first) } public inline fun Buffer.fold(initial: R, operation: A.(acc: R, T) -> R): R { var accumulator = initial - for (index in this.indices) accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) + for (index in this.offsetIndices) accumulator = elementAlgebra.operation(accumulator, getByOffset(index)) return accumulator } public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { val labels = labels var accumulator = initial - for (index in this.indices) accumulator = - elementAlgebra.operation(accumulator, getAbsolute(index), labels[index]) + for (index in this.offsetIndices) accumulator = + elementAlgebra.operation(accumulator, getByOffset(index), labels[index]) return accumulator } @@ -160,11 +173,11 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( other: Buffer, crossinline operation: A.(left: T, right: T) -> T, ): Series { - val newRange = indices.intersect(other.indices) + val newRange = offsetIndices.intersect(other.offsetIndices) return elementAlgebra.bufferFactory(newRange.size) { elementAlgebra.operation( - getAbsolute(it), - other.getAbsolute(it) + getByOffset(it), + other.getByOffset(it) ) }.moveTo(newRange.first) } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt index 882fa2c46..fa5e0addd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/seriesExtensions.kt @@ -12,32 +12,32 @@ import space.kscience.kmath.structures.Buffer public fun SeriesAlgebra.sin( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.sin(arg).moveTo(arg.offset) + bufferAlgebra.sin(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.cos( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.cos(arg).moveTo(arg.offset) + bufferAlgebra.cos(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.tan( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.tan(arg).moveTo(arg.offset) + bufferAlgebra.tan(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.asin( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.asin(arg).moveTo(arg.offset) + bufferAlgebra.asin(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.acos( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.acos(arg).moveTo(arg.offset) + bufferAlgebra.acos(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.atan( arg: Buffer, ): Series where BA : BufferAlgebra, BA : TrigonometricOperations> = - bufferAlgebra.atan(arg).moveTo(arg.offset) + bufferAlgebra.atan(arg).moveTo(arg.startOffset) //exponential @@ -45,42 +45,42 @@ public fun SeriesAlgebra.atan( public fun SeriesAlgebra.exp( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.exp(arg).moveTo(arg.offset) + bufferAlgebra.exp(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.ln( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.ln(arg).moveTo(arg.offset) + bufferAlgebra.ln(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.sinh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.sinh(arg).moveTo(arg.offset) + bufferAlgebra.sinh(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.cosh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.cosh(arg).moveTo(arg.offset) + bufferAlgebra.cosh(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.tanh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.tanh(arg).moveTo(arg.offset) + bufferAlgebra.tanh(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.asinh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.asinh(arg).moveTo(arg.offset) + bufferAlgebra.asinh(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.acosh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.acosh(arg).moveTo(arg.offset) + bufferAlgebra.acosh(arg).moveTo(arg.startOffset) public fun SeriesAlgebra.atanh( arg: Buffer, ): Series where BA : BufferAlgebra, BA : ExponentialOperations> = - bufferAlgebra.atanh(arg).moveTo(arg.offset) + bufferAlgebra.atanh(arg).moveTo(arg.startOffset) //power @@ -89,9 +89,9 @@ public fun SeriesAlgebra.power( arg: Buffer, pow: Number, ): Series where BA : BufferAlgebra, BA : PowerOperations> = - bufferAlgebra.power(arg, pow).moveTo(arg.offset) + bufferAlgebra.power(arg, pow).moveTo(arg.startOffset) public fun SeriesAlgebra.sqrt( arg: Buffer, ): Series where BA : BufferAlgebra, BA : PowerOperations> = - bufferAlgebra.sqrt(arg).moveTo(arg.offset) \ No newline at end of file + bufferAlgebra.sqrt(arg).moveTo(arg.startOffset) \ No newline at end of file From 72c70302974a1cc568f32a6c6242d7180c77a9fd Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 22:50:41 +0300 Subject: [PATCH 49/72] Add time series example stub --- examples/build.gradle.kts | 9 ++-- .../kscience/kmath/stat/DateTimeSeries.kt | 19 ++++++++ .../kmath/series/MonotonicSeriesAlgebra.kt | 47 +++++++++++++++++++ .../kscience/kmath/series/SeriesAlgebra.kt | 16 +++++-- 4 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index da645f012..f7b7794f3 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + plugins { kotlin("jvm") } @@ -33,6 +35,8 @@ dependencies { implementation(project(":kmath-multik")) implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") + //datetime + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") implementation("org.nd4j:nd4j-native:1.0.0-beta7") @@ -46,9 +50,6 @@ dependencies { // } else implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") - // multik implementation - implementation("org.jetbrains.kotlinx:multik-default:0.1.0") - implementation("org.slf4j:slf4j-simple:1.7.32") // plotting implementation("space.kscience:plotlykt-server:0.5.0") @@ -62,7 +63,7 @@ kotlin.sourceSets.all { } } -tasks.withType { +tasks.withType { kotlinOptions { jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt new file mode 100644 index 000000000..9836db6ea --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2023 KMath 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.stat + +import kotlinx.datetime.Instant +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.series.MonotonicSeriesAlgebra +import space.kscience.kmath.series.SeriesAlgebra +import kotlin.time.Duration + +fun SeriesAlgebra.Companion.time(zero: Instant, step: Duration) = MonotonicSeriesAlgebra( + bufferAlgebra = Double.algebra.bufferAlgebra, + offsetToLabel = { zero + step * it }, + labelToOffset = { (it - zero) / step } +) \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt new file mode 100644 index 000000000..2bc363934 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2018-2023 KMath 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.series + +import space.kscience.kmath.operations.BufferAlgebra +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.Buffer +import kotlin.math.ceil +import kotlin.math.floor + +/** + * A [SeriesAlgebra] with reverse label to index transformation. + * + * @param [labelToOffset] returns floating point number that is used for index resolution. + */ +public class MonotonicSeriesAlgebra, out BA : BufferAlgebra, L : Comparable>( + bufferAlgebra: BA, + offsetToLabel: (Int) -> L, + private val labelToOffset: (L) -> Double, +) : SeriesAlgebra(bufferAlgebra, offsetToLabel) { + + public val Buffer.labelRange: ClosedRange get() = offsetToLabel(startOffset)..offsetToLabel(startOffset + size) + + /** + * An offset of the given [label] rounded down + */ + public fun floorOffset(label: L): Int = floor(labelToOffset(label)).toInt() + + /** + * An offset of the given [label] rounded up + */ + public fun ceilOffset(label: L): Int = ceil(labelToOffset(label)).toInt() + + /** + * Get value by label (rounded down) or return null if the value is outside series boundaries. + */ + public fun Buffer.getByLabelOrNull(label: L): T? = getByOffsetOrNull(floorOffset(label)) + + /** + * Get value by label (rounded down) or throw [IndexOutOfBoundsException] if the value is outside series boundaries. + */ + public fun Buffer.getByLabel(label: L): T = getByLabelOrNull(label) + ?: throw IndexOutOfBoundsException("Label $label is not in $labelRange") +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt index 45e392693..1847e33b6 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/SeriesAlgebra.kt @@ -24,7 +24,9 @@ internal operator fun IntRange.contains(other: IntRange): Boolean = (other.first //TODO add permutation sort //TODO check rank statistics - +/** + * A [Buffer] with an offset relative to the [SeriesAlgebra] zero. + */ public interface Series : Buffer { public val origin: Buffer @@ -54,9 +56,9 @@ private class SeriesImpl( /** * A scope to operation on series */ -public class SeriesAlgebra, out BA : BufferAlgebra, L>( +public open class SeriesAlgebra, out BA : BufferAlgebra, L>( override val bufferAlgebra: BA, - private val labelResolver: (Int) -> L, + public val offsetToLabel: (Int) -> L, ) : RingOps>, StatisticalAlgebra { /** @@ -107,20 +109,22 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( */ public val Buffer.startOffset: Int get() = if (this is Series) position else 0 + public val Buffer.startLabel: L get() = offsetToLabel(startOffset) + /** * Build a new series positioned at [startOffset]. */ public fun series(size: Int, startOffset: Int = 0, block: A.(label: L) -> T): Series { return elementAlgebra.bufferFactory(size) { val index = it + startOffset - elementAlgebra.block(labelResolver(index)) + elementAlgebra.block(offsetToLabel(index)) }.moveTo(startOffset) } /** * Get a label buffer for given buffer. */ - public val Buffer.labels: List get() = offsetIndices.map(labelResolver) + public val Buffer.labels: List get() = offsetIndices.map(offsetToLabel) /** * Try to resolve element by label and return null if element with a given label is not found @@ -187,6 +191,8 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( override fun add(left: Buffer, right: Buffer): Series = left.zip(right) { l, r -> l + r } override fun multiply(left: Buffer, right: Buffer): Buffer = left.zip(right) { l, r -> l * r } + + public companion object } public fun , BA : BufferAlgebra, L> BA.seriesAlgebra(labels: Iterable): SeriesAlgebra { From 4c1ffdb6d9db3ea37ff159ad95958184bb8fd517 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Tue, 14 Mar 2023 13:50:42 +0300 Subject: [PATCH 50/72] search for shortest path algorithm --- .../kmath/trajectory/DubinsObstacle.kt | 24 +++++++----- .../kscience/kmath/trajectory/DubinsTest.kt | 39 ++++++++++++++++++- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index 6b247e55b..3aea139ec 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -136,7 +136,8 @@ public class DubinsObstacle( error("next tangent not found") } - public fun equals(other: DubinsObstacle): Boolean { + override fun equals(other: Any?): Boolean { + if (other == null || other !is DubinsObstacle) return false return this.circles == other.circles } } @@ -258,7 +259,7 @@ public fun constructTangentCircles(point: DoubleVector2D, val center2 = point + normalVectors(direction, r).second val p1 = center1 - point val p2 = center2 - point - return if (atan2(p1.y, p1.x) - atan2(p2.y, p2.x) in listOf(PI/2, -3*PI/2)) { + return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI/2, -3*PI/2)) { mapOf(DubinsPath.SimpleType.L to Circle2D(center1, r), DubinsPath.SimpleType.R to Circle2D(center2, r)) } @@ -270,7 +271,7 @@ public fun constructTangentCircles(point: DoubleVector2D, public fun sortedObstacles(currentObstacle: DubinsObstacle, obstacles: List): List { - return obstacles.sortedBy {norm(it.center - currentObstacle.center)}.reversed() + return obstacles.sortedBy {norm(it.center - currentObstacle.center)}//.reversed() } public fun tangentsAlongTheObstacle(initialCircle: Circle2D, @@ -389,13 +390,13 @@ public fun findAllPaths( } nextTangents = if (nextObstacle == finalObstacle) { nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection) and - (DubinsPath.toSimpleTypes(it.key)[0] == j)} + (DubinsPath.toSimpleTypes(it.key)[2] == j)} as MutableMap } else { nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} as MutableMap } - val tangentsAlong = mutableListOf() + var tangentsAlong = mutableListOf() for (tangent in nextTangents.values) { if (tangent.startCircle == line.last().endCircle) { val lengthMaxPossible = arcLength( @@ -413,7 +414,7 @@ public fun findAllPaths( tangent.lineSegment.begin, currentDirection) if (lengthCalculated > lengthMaxPossible) { - val tangentsAlong = tangentsAlongTheObstacle( + tangentsAlong = tangentsAlongTheObstacle( currentCircle, DubinsPath.toType(listOf( currentDirection, @@ -424,11 +425,11 @@ public fun findAllPaths( ) } else { - val tangentsAlong = mutableListOf() + tangentsAlong = mutableListOf() } } else { - val tangentsAlong = tangentsAlongTheObstacle( + tangentsAlong = tangentsAlongTheObstacle( currentCircle, DubinsPath.toType(listOf( currentDirection, @@ -456,6 +457,11 @@ public fun findAllPaths( )] = newOutputTangents } } + outputTangents[listOf( + i, + DubinsPath.SimpleType.S, + j + )] = newOutputTangents } for (lineId in outputTangents[listOf( i, @@ -505,7 +511,7 @@ public fun findAllPaths( )]!! + outputTangents[listOf( DubinsPath.SimpleType.R, DubinsPath.SimpleType.S, - DubinsPath.SimpleType.L)]!! + DubinsPath.SimpleType.R)]!! } diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index 16d77c84d..b26b21737 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -7,6 +7,8 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.DoubleVector2D +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.Euclidean2DSpace.minus import space.kscience.kmath.geometry.Euclidean2DSpace.vector import kotlin.test.Test import kotlin.test.assertTrue @@ -68,6 +70,18 @@ class DubinsTest { obstacles) val length = pathLength(shortestPath(outputTangents)) println(length) + for (path in outputTangents) { + println(pathLength(path)) + println(path.size) + for (tangent in path) { +// println(tangent.route) +// println(tangent.startCircle) +// println(tangent.endCircle) +// println(Euclidean2DSpace.norm(tangent.lineSegment.end - tangent.lineSegment.begin)) + } + println() + println() + } } @Test fun outerTangentsTest1() { @@ -78,7 +92,6 @@ class DubinsTest { Circle2D(vector(5.0, 5.0), 1.0) ) println(outerTangents(DubinsObstacle(circles1), DubinsObstacle(circles2))) - assertTrue(false) } @Test fun outerTangentsTest2() { @@ -100,6 +113,28 @@ class DubinsTest { } } } - assertTrue(false) + } + @Test + fun tangentsTest() { + val circle1 = Circle2D(vector(1.0, 6.5), 0.5) + val circle2 = Circle2D(vector(1.0, 6.5), 0.5) + val obstacle1 = DubinsObstacle(listOf(circle1)) + val obstacle2 = DubinsObstacle(listOf(circle2)) + val tangent = dubinsTangentsToCircles(circle1, circle2, obstacle1, obstacle2) + println(tangent) + } + @Test + fun equalCircles() { + val circle1 = Circle2D(vector(1.0, 6.5), 0.5) + val circle2 = Circle2D(vector(1.0, 6.5), 0.5) + println(circle1 == circle2) + } + @Test + fun equalObstacles() { + val circle1 = Circle2D(vector(1.0, 6.5), 0.5) + val circle2 = Circle2D(vector(1.0, 6.5), 0.5) + val obstacle1 = DubinsObstacle(listOf(circle1)) + val obstacle2 = DubinsObstacle(listOf(circle2)) + println(obstacle1 == obstacle2) } } \ No newline at end of file From 28b85b0f53ba5d6e5e82777ffa8d57a770860baa Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:13:34 +0300 Subject: [PATCH 51/72] Remove the choice of left-handed product. Refactor `vectorProduct`. Remove `leviChivita` function. --- .../kmath/geometry/Euclidean3DSpace.kt | 34 +++---------------- 1 file changed, 5 insertions(+), 29 deletions(-) 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 f1cf0bad2..38c252bc0 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 @@ -103,45 +103,21 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< override fun DoubleVector3D.dot(other: DoubleVector3D): Double = x * other.x + y * other.y + z * other.z - private fun leviCivita(i: Int, j: Int, k: Int): Int = when { - // even permutation - i == 0 && j == 1 && k == 2 -> 1 - i == 1 && j == 2 && k == 0 -> 1 - i == 2 && j == 0 && k == 1 -> 1 - // odd permutations - i == 2 && j == 1 && k == 0 -> -1 - i == 0 && j == 2 && k == 1 -> -1 - i == 1 && j == 0 && k == 2 -> -1 - - else -> 0 - } - /** - * Compute vector product of [first] and [second]. The basis assumed to be right-handed if [rightBasis] is true and - * left-handed otherwise + * Compute vector product of [first] and [second]. The basis assumed to be right-handed. */ public fun vectorProduct( first: DoubleVector3D, second: DoubleVector3D, - rightBasis: Boolean = true, ): DoubleVector3D { - var x = 0.0 - var y = 0.0 - var z = 0.0 + val (x1, y1, z1) = first + val (x2, y2, z2) = second - for (j in (0..2)) { - for (k in (0..2)) { - x += leviCivita(0, j, k) * first[j] * second[k] - y += leviCivita(1, j, k) * first[j] * second[k] - z += leviCivita(2, j, k) * first[j] * second[k] - } - } - - return vector(x, y, z) * (if (rightBasis) 1 else -1) + return vector(y1 * z2 - y2 * z2, z1 * x2 - z2 * x2, x1 * y2 - x2 * y2) } /** - * Vector product with right basis + * Vector product with a right basis */ public infix fun DoubleVector3D.cross(other: DoubleVector3D): Vector3D = vectorProduct(this, other) From cd2ade881add23d4ac9b3f4b4d5ea594b6ad6d63 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Mar 2023 09:33:17 +0300 Subject: [PATCH 52/72] Revert "Remove the choice of left-handed product. Refactor `vectorProduct`. Remove `leviChivita` function." This reverts commit 28b85b0f53ba5d6e5e82777ffa8d57a770860baa. --- .../kmath/geometry/Euclidean3DSpace.kt | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) 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 38c252bc0..f1cf0bad2 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 @@ -103,21 +103,45 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< override fun DoubleVector3D.dot(other: DoubleVector3D): Double = x * other.x + y * other.y + z * other.z + private fun leviCivita(i: Int, j: Int, k: Int): Int = when { + // even permutation + i == 0 && j == 1 && k == 2 -> 1 + i == 1 && j == 2 && k == 0 -> 1 + i == 2 && j == 0 && k == 1 -> 1 + // odd permutations + i == 2 && j == 1 && k == 0 -> -1 + i == 0 && j == 2 && k == 1 -> -1 + i == 1 && j == 0 && k == 2 -> -1 + + else -> 0 + } + /** - * Compute vector product of [first] and [second]. The basis assumed to be right-handed. + * Compute vector product of [first] and [second]. The basis assumed to be right-handed if [rightBasis] is true and + * left-handed otherwise */ public fun vectorProduct( first: DoubleVector3D, second: DoubleVector3D, + rightBasis: Boolean = true, ): DoubleVector3D { - val (x1, y1, z1) = first - val (x2, y2, z2) = second + var x = 0.0 + var y = 0.0 + var z = 0.0 - return vector(y1 * z2 - y2 * z2, z1 * x2 - z2 * x2, x1 * y2 - x2 * y2) + for (j in (0..2)) { + for (k in (0..2)) { + x += leviCivita(0, j, k) * first[j] * second[k] + y += leviCivita(1, j, k) * first[j] * second[k] + z += leviCivita(2, j, k) * first[j] * second[k] + } + } + + return vector(x, y, z) * (if (rightBasis) 1 else -1) } /** - * Vector product with a right basis + * Vector product with right basis */ public infix fun DoubleVector3D.cross(other: DoubleVector3D): Vector3D = vectorProduct(this, other) From ef336af87ddb6df9acc8029e9633234ae5fe6851 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Mar 2023 09:37:03 +0300 Subject: [PATCH 53/72] Fix vector product --- .gitignore | 3 ++- CHANGELOG.md | 1 + examples/build.gradle.kts | 14 +++++----- gradle.properties | 2 +- .../space/kscience/kmath/nd/BufferND.kt | 26 +++++++++++++++++++ .../integration/GaussIntegratorRuleFactory.kt | 2 -- .../kmath/geometry/Euclidean3DSpace.kt | 6 ++--- .../kmath/geometry/Euclidean3DSpaceTest.kt | 1 - 8 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 34ddf3fd9..7713a9f96 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ out/ !/.idea/copyright/ !/.idea/scopes/ -/kotlin-js-store/yarn.lock +/gradle/yarn.lock + diff --git a/CHANGELOG.md b/CHANGELOG.md index 404366a03..c5fa3f372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] ### Added +- Generic builders for `BufferND` and `MutableBufferND` - `NamedMatrix` - matrix with symbol-based indexing - `Expression` with default arguments - Type-aliases for numbers like `Float64` diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f7b7794f3..50708eaa9 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -55,17 +55,19 @@ dependencies { implementation("space.kscience:plotlykt-server:0.5.0") } -kotlin.sourceSets.all { - with(languageSettings) { - optIn("kotlin.contracts.ExperimentalContracts") - optIn("kotlin.ExperimentalUnsignedTypes") - optIn("space.kscience.kmath.misc.UnstableKMathAPI") +kotlin { + jvmToolchain(11) + sourceSets.all { + with(languageSettings) { + optIn("kotlin.contracts.ExperimentalContracts") + optIn("kotlin.ExperimentalUnsignedTypes") + optIn("space.kscience.kmath.misc.UnstableKMathAPI") + } } } tasks.withType { kotlinOptions { - jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" } } diff --git a/gradle.properties b/gradle.properties index 048c9c9f3..cded5934c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.3-kotlin-1.8.20-RC +toolsVersion=0.14.4-kotlin-1.8.20-RC org.gradle.parallel=true 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 55e8bbcf8..a6bab8be1 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 @@ -7,7 +7,9 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory /** * Represents [StructureND] over [Buffer]. @@ -29,6 +31,18 @@ public open class BufferND( override fun toString(): String = StructureND.toString(this) } +/** + * Create a generic [BufferND] using provided [initializer] + */ +public fun BufferND( + shape: ShapeND, + bufferFactory: BufferFactory = BufferFactory.boxing(), + initializer: (IntArray) -> T, +): BufferND { + val strides = Strides(shape) + return BufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) }) +} + ///** // * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] // */ @@ -67,6 +81,18 @@ public open class MutableBufferND( } } +/** + * Create a generic [BufferND] using provided [initializer] + */ +public fun MutableBufferND( + shape: ShapeND, + bufferFactory: MutableBufferFactory = MutableBufferFactory.boxing(), + initializer: (IntArray) -> T, +): MutableBufferND { + val strides = Strides(shape) + return MutableBufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) }) +} + ///** // * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] // */ 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 fc76ea819..4ed4965c9 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 @@ -9,7 +9,6 @@ import space.kscience.kmath.operations.mapToBuffer import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer -import kotlin.jvm.Synchronized import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal @@ -57,7 +56,6 @@ public object GaussLegendreRuleFactory : GaussIntegratorRuleFactory { private val cache = HashMap, Buffer>>() - @Synchronized private fun getOrBuildRule(numPoints: Int): Pair, Buffer> = cache.getOrPut(numPoints) { buildRule(numPoints) } 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 f1cf0bad2..3059cefe6 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 @@ -117,13 +117,11 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< } /** - * Compute vector product of [first] and [second]. The basis assumed to be right-handed if [rightBasis] is true and - * left-handed otherwise + * Compute vector product of [first] and [second]. The basis assumed to be right-handed. */ public fun vectorProduct( first: DoubleVector3D, second: DoubleVector3D, - rightBasis: Boolean = true, ): DoubleVector3D { var x = 0.0 var y = 0.0 @@ -137,7 +135,7 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< } } - return vector(x, y, z) * (if (rightBasis) 1 else -1) + return vector(x, y, z) } /** 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 291b0ad47..20e112ad1 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 @@ -78,7 +78,6 @@ internal class Euclidean3DSpaceTest { assertVectorEquals(zAxis, vectorProduct(xAxis, yAxis)) assertVectorEquals(zAxis, xAxis cross yAxis) assertVectorEquals(-zAxis, vectorProduct(yAxis, xAxis)) - assertVectorEquals(zAxis, vectorProduct(yAxis, xAxis, rightBasis = false)) } @Test From c36af3515e08adb3595a95a6470309eb149fc0c9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 18:39:27 +0300 Subject: [PATCH 54/72] Update trajectory description --- kmath-trajectory/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts index 689c3265b..32b87bb06 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -15,7 +15,7 @@ kscience{ } readme { - description = "Path and trajectory optimization" - maturity = space.kscience.gradle.Maturity.PROTOTYPE + description = "Path and trajectory optimization (to be moved to a separate project)" + maturity = space.kscience.gradle.Maturity.DEPRECATED propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) } From 62c8610a9ebb45d5c450ef283ce21ec5e0d4de3c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 19:16:46 +0300 Subject: [PATCH 55/72] Update publishing CD --- .github/workflows/publish.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 794881b09..8087195c2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v3.0.0 - - uses: actions/setup-java@v3.0.0 + - uses: actions/setup-java@v3.10.0 with: java-version: 11 distribution: liberica @@ -26,26 +26,24 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- - - uses: gradle/wrapper-validation-action@v1.0.4 - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' - uses: gradle/gradle-build-action@v2.1.5 + uses: gradle/gradle-build-action@v2.4.0 with: arguments: | - releaseAll + publishAllPublicationsToSpaceRepository -Ppublishing.enabled=true - -Ppublishing.sonatype=false -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} - name: Publish Mac Artifacts if: matrix.os == 'macOS-latest' - uses: gradle/gradle-build-action@v2.1.5 + uses: gradle/gradle-build-action@v2.4.0 with: arguments: | - releaseMacosX64 - releaseIosArm64 - releaseIosX64 + publishMacosX64PublicationsToSpaceRepository + publishIosX64PublicationsToSpaceRepository + publishIosArm64PublicationsToSpaceRepository + publishIosSimulatorArm64PublicationsToSpaceRepository -Ppublishing.enabled=true - -Ppublishing.sonatype=false -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} From c442eb7e94ff562688b171cfcdf7deb829b71d47 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 19:41:31 +0300 Subject: [PATCH 56/72] Fix publish task names --- .github/workflows/publish.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8087195c2..0ac8805e0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,10 +40,10 @@ jobs: uses: gradle/gradle-build-action@v2.4.0 with: arguments: | - publishMacosX64PublicationsToSpaceRepository - publishIosX64PublicationsToSpaceRepository - publishIosArm64PublicationsToSpaceRepository - publishIosSimulatorArm64PublicationsToSpaceRepository + publishMacosX64PublicationToSpaceRepository + publishIosX64PublicationToSpaceRepository + publishIosArm64PublicationToSpaceRepository + publishIosSimulatorArm64PublicationToSpaceRepository -Ppublishing.enabled=true -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} From 81213eb94340fc87ae6958d30e598d234439dc35 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Tue, 21 Mar 2023 12:04:27 +0300 Subject: [PATCH 57/72] search for shortest path algorithm --- .../kmath/trajectory/DubinsObstacle.kt | 87 +++++++++---------- .../kscience/kmath/trajectory/DubinsTest.kt | 50 +---------- 2 files changed, 45 insertions(+), 92 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index 3aea139ec..896803fba 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -39,8 +39,6 @@ public class DubinsObstacle( var angle2: Double val routes = mapOf( DubinsPath.Type.RSR to Pair(radius, other.radius), -// DubinsPath.Type.RSL to Pair(radius, -other.radius), -// DubinsPath.Type.LSR to Pair(-radius, other.radius), DubinsPath.Type.LSL to Pair(-radius, -other.radius) ) return buildMap { @@ -76,8 +74,7 @@ public class DubinsObstacle( } } } -// val firstCircles = this.circles.slice(-this.circles.size..-1) -// val secondCircles = this.circles.slice(-this.circles.size+1..0) + val firstCircles = this.circles val secondCircles = this.circles.slice(1..this.circles.lastIndex) + this.circles[0] @@ -149,7 +146,7 @@ public data class DubinsTangent(val startCircle: Circle2D, val lineSegment: LineSegment2D, val route: PathTypes) -public fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { +private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { return v1.x * v2.y - v1.y * v2.x } @@ -164,7 +161,7 @@ public fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { return true } -public fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { +private fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { val a = (this.begin.x - this.end.x).pow(2.0) + (this.begin.y - this.end.y).pow(2.0) val b = 2 * ((this.begin.x - this.end.x) * (this.end.x - circle.center.x) + (this.begin.y - this.end.y) * (this.end.y - circle.center.y)) @@ -184,7 +181,7 @@ public fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { return false } -public fun DubinsTangent.intersectObstacle(obstacle: DubinsObstacle): Boolean { +private fun DubinsTangent.intersectObstacle(obstacle: DubinsObstacle): Boolean { for (tangent in obstacle.tangents) { if (this.lineSegment.intersectSegment(tangent.lineSegment)) { return true @@ -198,7 +195,7 @@ public fun DubinsTangent.intersectObstacle(obstacle: DubinsObstacle): Boolean { return false } -public fun outerTangents(first: DubinsObstacle, second: DubinsObstacle): MutableMap { +private fun outerTangents(first: DubinsObstacle, second: DubinsObstacle): MutableMap { return buildMap { for (circle1 in first.circles) { for (circle2 in second.circles) { @@ -216,7 +213,7 @@ public fun outerTangents(first: DubinsObstacle, second: DubinsObstacle): Mutable }.toMutableMap() } -public fun arcLength(circle: Circle2D, +private fun arcLength(circle: Circle2D, point1: DoubleVector2D, point2: DoubleVector2D, route: DubinsPath.SimpleType): Double { @@ -245,14 +242,14 @@ public fun arcLength(circle: Circle2D, return circle.radius * angle } -public fun normalVectors(v: DoubleVector2D, r: Double): Pair { +private fun normalVectors(v: DoubleVector2D, r: Double): Pair { return Pair( r * vector(v.y / norm(v), -v.x / norm(v)), r * vector(-v.y / norm(v), v.x / norm(v)) ) } -public fun constructTangentCircles(point: DoubleVector2D, +private fun constructTangentCircles(point: DoubleVector2D, direction: DoubleVector2D, r: Double): Map { val center1 = point + normalVectors(direction, r).first @@ -269,12 +266,12 @@ public fun constructTangentCircles(point: DoubleVector2D, } } -public fun sortedObstacles(currentObstacle: DubinsObstacle, +private fun sortedObstacles(currentObstacle: DubinsObstacle, obstacles: List): List { return obstacles.sortedBy {norm(it.center - currentObstacle.center)}//.reversed() } -public fun tangentsAlongTheObstacle(initialCircle: Circle2D, +private fun tangentsAlongTheObstacle(initialCircle: Circle2D, initialRoute: DubinsPath.Type, finalCircle: Circle2D, obstacle: DubinsObstacle): MutableList { @@ -288,7 +285,7 @@ public fun tangentsAlongTheObstacle(initialCircle: Circle2D, return dubinsTangents } -public fun allFinished(paths: List>, +private fun allFinished(paths: List>, finalObstacle: DubinsObstacle): Boolean { for (path in paths) { if (path.last().endObstacle != finalObstacle) { @@ -333,28 +330,28 @@ public fun findAllPaths( finalPoint, finalDirection, finalRadius) - var outputTangents = mutableMapOf>>() + var path = mutableMapOf>>() for (i in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { for (j in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { val finalCircle = finalCircles[j]!! val finalObstacle = DubinsObstacle(listOf(finalCircle)) - outputTangents[listOf(i, - DubinsPath.SimpleType.S, - j)] = mutableListOf( - mutableListOf(DubinsTangent( - initialCircles[i]!!, - initialCircles[i]!!, - DubinsObstacle(listOf(initialCircles[i]!!)), - DubinsObstacle(listOf(initialCircles[i]!!)), - LineSegment2D(startingPoint, startingPoint), - listOf(i, DubinsPath.SimpleType.S, i) - ))) - var currentObstacle = DubinsObstacle(listOf(initialCircles[i]!!)) - while (!allFinished(outputTangents[listOf(i, + path[listOf(i, + DubinsPath.SimpleType.S, + j)] = mutableListOf( + mutableListOf(DubinsTangent( + initialCircles[i]!!, + initialCircles[i]!!, + DubinsObstacle(listOf(initialCircles[i]!!)), + DubinsObstacle(listOf(initialCircles[i]!!)), + LineSegment2D(startingPoint, startingPoint), + listOf(i, DubinsPath.SimpleType.S, i) + ))) + //var currentObstacle = DubinsObstacle(listOf(initialCircles[i]!!)) + while (!allFinished(path[listOf(i, DubinsPath.SimpleType.S, j)]!!, finalObstacle)) { - var newOutputTangents = mutableListOf>() - for (line in outputTangents[listOf(i, + var newPaths = mutableListOf>() + for (line in path[listOf(i, DubinsPath.SimpleType.S, j)]!!) { var currentCircle = line.last().endCircle @@ -439,41 +436,41 @@ public fun findAllPaths( currentObstacle ) } - newOutputTangents.add((line + tangentsAlong + listOf(tangent)).toMutableList()) + newPaths.add((line + tangentsAlong + listOf(tangent)).toMutableList()) } - outputTangents[listOf( + path[listOf( i, DubinsPath.SimpleType.S, j - )] = newOutputTangents + )] = newPaths } else { // minor changes from Python code - newOutputTangents.add(line) - outputTangents[listOf( + newPaths.add(line) + path[listOf( i, DubinsPath.SimpleType.S, j - )] = newOutputTangents + )] = newPaths } } - outputTangents[listOf( + path[listOf( i, DubinsPath.SimpleType.S, j - )] = newOutputTangents + )] = newPaths } - for (lineId in outputTangents[listOf( + for (lineId in path[listOf( i, DubinsPath.SimpleType.S, j )]!!.indices) { - val lastDirection = outputTangents[listOf( + val lastDirection = path[listOf( i, DubinsPath.SimpleType.S, j )]!![lineId].last().route[2] - outputTangents[listOf( + path[listOf( i, DubinsPath.SimpleType.S, j @@ -496,19 +493,19 @@ public fun findAllPaths( } } } - return outputTangents[listOf( + return path[listOf( DubinsPath.SimpleType.L, DubinsPath.SimpleType.S, DubinsPath.SimpleType.L - )]!! + outputTangents[listOf( + )]!! + path[listOf( DubinsPath.SimpleType.L, DubinsPath.SimpleType.S, DubinsPath.SimpleType.R - )]!! + outputTangents[listOf( + )]!! + path[listOf( DubinsPath.SimpleType.R, DubinsPath.SimpleType.S, DubinsPath.SimpleType.L - )]!! + outputTangents[listOf( + )]!! + path[listOf( DubinsPath.SimpleType.R, DubinsPath.SimpleType.S, DubinsPath.SimpleType.R)]!! diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index b26b21737..a78a5317d 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -6,12 +6,8 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.DoubleVector2D -import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.Euclidean2DSpace.minus import space.kscience.kmath.geometry.Euclidean2DSpace.vector import kotlin.test.Test -import kotlin.test.assertTrue class DubinsTest { @Test @@ -60,7 +56,7 @@ class DubinsTest { Circle2D(vector(9.0, 4.0), 0.5) )) ) - val outputTangents = findAllPaths( + val paths = findAllPaths( startPoint, startDirection, startRadius, @@ -68,9 +64,9 @@ class DubinsTest { finalDirection, finalRadius, obstacles) - val length = pathLength(shortestPath(outputTangents)) + val length = pathLength(shortestPath(paths)) println(length) - for (path in outputTangents) { + for (path in paths) { println(pathLength(path)) println(path.size) for (tangent in path) { @@ -84,46 +80,6 @@ class DubinsTest { } } @Test - fun outerTangentsTest1() { - // works incorrectly - val circles1 = listOf( - Circle2D(vector(0.0, 0.0), 1.0)) - val circles2 = listOf( - Circle2D(vector(5.0, 5.0), 1.0) - ) - println(outerTangents(DubinsObstacle(circles1), DubinsObstacle(circles2))) - } - @Test - fun outerTangentsTest2() { - // works incorrectly - val circles1 = listOf( - Circle2D(vector(0.0, 0.0), 1.0), - Circle2D(vector( 2.0, 0.0), 1.0)) - val circles2 = listOf( - Circle2D(vector(5.0, 5.0), 1.0), - Circle2D(vector(7.0, 5.0), 1.0) - ) - println(outerTangents(DubinsObstacle(circles1), DubinsObstacle(circles2))) - - for (circle1 in circles1) { - for (circle2 in circles2) { - for (tangent in dubinsTangentsToCircles(circle1, circle2, - DubinsObstacle(circles1), DubinsObstacle(circles2))) { - println(tangent) - } - } - } - } - @Test - fun tangentsTest() { - val circle1 = Circle2D(vector(1.0, 6.5), 0.5) - val circle2 = Circle2D(vector(1.0, 6.5), 0.5) - val obstacle1 = DubinsObstacle(listOf(circle1)) - val obstacle2 = DubinsObstacle(listOf(circle2)) - val tangent = dubinsTangentsToCircles(circle1, circle2, obstacle1, obstacle2) - println(tangent) - } - @Test fun equalCircles() { val circle1 = Circle2D(vector(1.0, 6.5), 0.5) val circle2 = Circle2D(vector(1.0, 6.5), 0.5) From 56bba749c026863a02ed6eb461d85d29d56e81e6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 22 Mar 2023 10:54:24 +0300 Subject: [PATCH 58/72] Update publishing --- .github/workflows/publish.yml | 4 ++-- gradle.properties | 2 +- .../kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0ac8805e0..471388364 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -32,7 +32,7 @@ jobs: with: arguments: | publishAllPublicationsToSpaceRepository - -Ppublishing.enabled=true + -Ppublishing.targets=all -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} - name: Publish Mac Artifacts @@ -44,6 +44,6 @@ jobs: publishIosX64PublicationToSpaceRepository publishIosArm64PublicationToSpaceRepository publishIosSimulatorArm64PublicationToSpaceRepository - -Ppublishing.enabled=true + -Ppublishing.targets=all -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} diff --git a/gradle.properties b/gradle.properties index cded5934c..262bcabfb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.4-kotlin-1.8.20-RC +toolsVersion=0.14.5-kotlin-1.8.20-RC org.gradle.parallel=true 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 2fd4f0057..48be93b87 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 @@ -8,6 +8,7 @@ package space.kscience.kmath.coroutines import kotlinx.coroutines.* +import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.produce import kotlinx.coroutines.flow.* @@ -57,7 +58,7 @@ public suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCol coroutineScope { //Starting up to N deferred coroutines ahead of time - val channel = produce(capacity = concurrency - 1) { + val channel: ReceiveChannel> = produce(capacity = concurrency - 1) { deferredFlow.collect { value -> value.start(this@coroutineScope) send(value) From d87eefcaa359f92a9a35c34784e196f767aa2836 Mon Sep 17 00:00:00 2001 From: SPC-code <112205870+SPC-code@users.noreply.github.com> Date: Wed, 22 Mar 2023 18:04:16 +0300 Subject: [PATCH 59/72] Add macOsArm64 to publish.yml --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 471388364..ab9243f15 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,6 +41,7 @@ jobs: with: arguments: | publishMacosX64PublicationToSpaceRepository + publishMacosArm64PublicationToSpaceRepository publishIosX64PublicationToSpaceRepository publishIosArm64PublicationToSpaceRepository publishIosSimulatorArm64PublicationToSpaceRepository From ea5305c8d878e910128543f44453fe7e20294164 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:28:02 +0300 Subject: [PATCH 60/72] search for shortest path algorithm --- .../kscience/kmath/trajectory/DubinsTest.kt | 18 ++++-------------- .../kscience/kmath/trajectory/TangentTest.kt | 15 +-------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index a78a5317d..fdc3bd3c7 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.vector +import space.kscience.kmath.geometry.equalsFloat import kotlin.test.Test +import kotlin.test.assertTrue class DubinsTest { @Test @@ -31,7 +33,7 @@ class DubinsTest { finalRadius, obstacles) val length = pathLength(shortestPath(outputTangents)) - println(length) + assertTrue(length.equalsFloat(27.2113183)) } @Test @@ -65,19 +67,7 @@ class DubinsTest { finalRadius, obstacles) val length = pathLength(shortestPath(paths)) - println(length) - for (path in paths) { - println(pathLength(path)) - println(path.size) - for (tangent in path) { -// println(tangent.route) -// println(tangent.startCircle) -// println(tangent.endCircle) -// println(Euclidean2DSpace.norm(tangent.lineSegment.end - tangent.lineSegment.begin)) - } - println() - println() - } + assertTrue(length.equalsFloat(28.9678224)) } @Test fun equalCircles() { diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt index 6d4493124..2ae89038c 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt @@ -12,6 +12,7 @@ import space.kscience.kmath.geometry.LineSegment import space.kscience.kmath.geometry.equalsLine import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFailsWith import kotlin.test.assertTrue class TangentTest { @@ -60,18 +61,4 @@ class TangentTest { val c2 = Circle2D(vector(0.0, 0.0), 1.0) assertEquals(emptyMap(), c1.tangentsToCircle(c2)) } -// -// @Test -// fun nonExistingTangents() { -// assertFailsWith { -// val c1 = Circle2D(vector(0.0, 0.0), 1.0) -// val c2 = Circle2D(vector(2.0, 0.0), 1.0) -// c1.tangentsToCircle(c2) -// } -// assertFailsWith { -// val c1 = Circle2D(vector(0.0, 0.0), 1.0) -// val c2 = Circle2D(vector(0.5, 0.0), 1.0) -// c1.tangentsToCircle(c2) -// } -// } } \ No newline at end of file From 24c39c97cd4b9186a8445dedffff4c7fcc3e5ca1 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:30:13 +0300 Subject: [PATCH 61/72] search for shortest path algorithm --- .../kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt index 896803fba..ee0b58a15 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt @@ -255,7 +255,6 @@ private fun constructTangentCircles(point: DoubleVector2D, val center1 = point + normalVectors(direction, r).first val center2 = point + normalVectors(direction, r).second val p1 = center1 - point - val p2 = center2 - point return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI/2, -3*PI/2)) { mapOf(DubinsPath.SimpleType.L to Circle2D(center1, r), DubinsPath.SimpleType.R to Circle2D(center2, r)) From 11dd4088d977f5c2ecacfe264e77bf432a44a8e3 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:39:51 +0300 Subject: [PATCH 62/72] search for shortest path algorithm --- .../kotlin/space/kscience/kmath/trajectory/DubinsTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt index fdc3bd3c7..07e9861c7 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt @@ -9,6 +9,7 @@ import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.vector import space.kscience.kmath.geometry.equalsFloat import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertTrue class DubinsTest { @@ -33,7 +34,7 @@ class DubinsTest { finalRadius, obstacles) val length = pathLength(shortestPath(outputTangents)) - assertTrue(length.equalsFloat(27.2113183)) + assertEquals(length, 27.2113183, 1e-6) } @Test @@ -67,7 +68,7 @@ class DubinsTest { finalRadius, obstacles) val length = pathLength(shortestPath(paths)) - assertTrue(length.equalsFloat(28.9678224)) + assertEquals(length,28.9678224, 1e-6) } @Test fun equalCircles() { From f809e40791f73ab33bb05d3a23947fe8af310f98 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 11:42:58 +0300 Subject: [PATCH 63/72] Disentangle obstacle code phase 1 --- .../kmath/trajectory/DubinsObstacle.kt | 519 --------------- .../kscience/kmath/trajectory/DubinsPath.kt | 241 ++----- .../kscience/kmath/trajectory/Obstacle.kt | 619 ++++++++++++++++++ .../kscience/kmath/trajectory/Trajectory2D.kt | 34 +- .../kscience/kmath/trajectory/tangent.kt | 114 ---- .../trajectory/{dubins => }/DubinsTests.kt | 7 +- .../{DubinsTest.kt => ObstacleTest.kt} | 65 +- .../kmath/trajectory/segments/ArcTests.kt | 3 +- 8 files changed, 748 insertions(+), 854 deletions(-) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt rename kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/{dubins => }/DubinsTests.kt (93%) rename kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/{DubinsTest.kt => ObstacleTest.kt} (55%) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt deleted file mode 100644 index ee0b58a15..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsObstacle.kt +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.* -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Euclidean2DSpace.minus -import space.kscience.kmath.geometry.Euclidean2DSpace.plus -import space.kscience.kmath.geometry.Euclidean2DSpace.times -import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.geometry.Euclidean2DSpace.norm -import space.kscience.kmath.operations.DoubleField.pow -import kotlin.math.* - -public fun LineSegment2D.length(): Double { - return ((end.y - begin.y).pow(2.0) + (end.x - begin.x).pow(2.0)).pow(0.5) -} -public class DubinsObstacle( - public val circles: List -) { - public val tangents: List = boundaryTangents().first - public val boundaryRoute: DubinsPath.Type = boundaryTangents().second - public val center: Vector2D = - vector(this.circles.sumOf{it.center.x} / this.circles.size, - this.circles.sumOf{it.center.y} / this.circles.size) - private fun boundaryTangents(): Pair, DubinsPath.Type> { - // outer tangents for a polygon circles can be either lsl or rsr - - fun Circle2D.dubinsTangentsToCircles( - other: Circle2D, - ): Map = with(Euclidean2DSpace) { - val line = LineSegment(center, other.center) - val d = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(radius, other.radius), - DubinsPath.Type.LSL to Pair(-radius, -other.radius) - ) - return buildMap { - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (d * d >= r * r) { - val l = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put(route, DubinsTangent(Circle2D(center, radius), - other, - this@DubinsObstacle, - this@DubinsObstacle, - LineSegment2D( - center + w * r1, - other.center + w * r2 - ), - DubinsPath.toSimpleTypes(route)) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } - } - - val firstCircles = this.circles - val secondCircles = this.circles.slice(1..this.circles.lastIndex) + - this.circles[0] - val lslTangents = firstCircles.zip(secondCircles) - {a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.LSL]!!} - val rsrTangents = firstCircles.zip(secondCircles) - {a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.RSR]!!} - val center = vector( - this.circles.sumOf { it.center.x } / this.circles.size, - this.circles.sumOf { it.center.y } / this.circles.size - ) - val lslToCenter = lslTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + - lslTangents.sumOf { it.lineSegment.end.distanceTo(center) } - val rsrToCenter = rsrTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + - rsrTangents.sumOf { it.lineSegment.end.distanceTo(center) } - return if (rsrToCenter >= lslToCenter) { - Pair(rsrTangents, DubinsPath.Type.RSR) - } else { - Pair(lslTangents, DubinsPath.Type.LSL) - } - } - - public fun nextTangent(circle: Circle2D, route: DubinsPath.Type): DubinsTangent { - if (route == this.boundaryRoute) { - for (i in this.circles.indices) { - if (this.circles[i] == circle) { - return this.tangents[i] - } - } - } - else { - for (i in this.circles.indices) { - if (this.circles[i] == circle) { - if (i > 0) { - return DubinsTangent(this.circles[i], - this.circles[i-1], - this, - this, - LineSegment2D(this.tangents[i-1].lineSegment.end, - this.tangents[i-1].lineSegment.begin), - DubinsPath.toSimpleTypes(route)) - } - else { - return DubinsTangent(this.circles[0], - this.circles.last(), - this, - this, - LineSegment2D(this.tangents.last().lineSegment.end, - this.tangents.last().lineSegment.begin), - DubinsPath.toSimpleTypes(route)) - } - } - } - } - - error("next tangent not found") - } - - override fun equals(other: Any?): Boolean { - if (other == null || other !is DubinsObstacle) return false - return this.circles == other.circles - } -} - -public data class DubinsTangent(val startCircle: Circle2D, - val endCircle: Circle2D, - val startObstacle: DubinsObstacle, - val endObstacle: DubinsObstacle, - val lineSegment: LineSegment2D, - val route: PathTypes) - -private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { - fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { - return v1.x * v2.y - v1.y * v2.x - } - if (crossProduct(other.begin - this.begin, other.end - this.begin).sign == - crossProduct(other.begin - this.end, other.end - this.end).sign) { - return false - } - if (crossProduct(this.begin - other.begin, this.end - other.begin).sign == - crossProduct(this.begin - other.end, this.end - other.end).sign) { - return false - } - return true -} - -private fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { - val a = (this.begin.x - this.end.x).pow(2.0) + (this.begin.y - this.end.y).pow(2.0) - val b = 2 * ((this.begin.x - this.end.x) * (this.end.x - circle.center.x) + - (this.begin.y - this.end.y) * (this.end.y - circle.center.y)) - val c = (this.end.x - circle.center.x).pow(2.0) + (this.end.y - circle.center.y).pow(2.0) - - circle.radius.pow(2.0) - val d = b.pow(2.0) - 4 * a * c - if (d < 1e-6) { - return false - } - else { - val t1 = (-b - d.pow(0.5)) * 0.5 / a - val t2 = (-b + d.pow(0.5)) * 0.5 / a - if (((0 < t1) and (t1 < 1)) or ((0 < t2) and (t2 < 1))) { - return true - } - } - return false -} - -private fun DubinsTangent.intersectObstacle(obstacle: DubinsObstacle): Boolean { - for (tangent in obstacle.tangents) { - if (this.lineSegment.intersectSegment(tangent.lineSegment)) { - return true - } - } - for (circle in obstacle.circles) { - if (this.lineSegment.intersectCircle(circle)) { - return true - } - } - return false -} - -private fun outerTangents(first: DubinsObstacle, second: DubinsObstacle): MutableMap { - return buildMap { - for (circle1 in first.circles) { - for (circle2 in second.circles) { - for (tangent in dubinsTangentsToCircles(circle1, circle2, first, second)) { - if (!(tangent.value.intersectObstacle(first)) - and !(tangent.value.intersectObstacle(second))) { - put( - tangent.key, - tangent.value - ) - } - } - } - } - }.toMutableMap() -} - -private fun arcLength(circle: Circle2D, - point1: DoubleVector2D, - point2: DoubleVector2D, - route: DubinsPath.SimpleType): Double { - val phi1 = atan2(point1.y - circle.center.y, point1.x - circle.center.x) - val phi2 = atan2(point2.y - circle.center.y, point2.x - circle.center.x) - var angle = 0.0 - when (route) { - DubinsPath.SimpleType.L -> { - angle = if (phi2 >= phi1) { - phi2 - phi1 - } else { - 2 * PI + phi2 - phi1 - } - } - DubinsPath.SimpleType.R -> { - angle = if (phi2 >= phi1) { - 2 * PI - (phi2 - phi1) - } else { - -(phi2 - phi1) - } - } - DubinsPath.SimpleType.S -> { - error("L or R route is expected") - } - } - return circle.radius * angle -} - -private fun normalVectors(v: DoubleVector2D, r: Double): Pair { - return Pair( - r * vector(v.y / norm(v), -v.x / norm(v)), - r * vector(-v.y / norm(v), v.x / norm(v)) - ) -} - -private fun constructTangentCircles(point: DoubleVector2D, - direction: DoubleVector2D, - r: Double): Map { - val center1 = point + normalVectors(direction, r).first - val center2 = point + normalVectors(direction, r).second - val p1 = center1 - point - return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI/2, -3*PI/2)) { - mapOf(DubinsPath.SimpleType.L to Circle2D(center1, r), - DubinsPath.SimpleType.R to Circle2D(center2, r)) - } - else { - mapOf(DubinsPath.SimpleType.L to Circle2D(center2, r), - DubinsPath.SimpleType.R to Circle2D(center1, r)) - } -} - -private fun sortedObstacles(currentObstacle: DubinsObstacle, - obstacles: List): List { - return obstacles.sortedBy {norm(it.center - currentObstacle.center)}//.reversed() -} - -private fun tangentsAlongTheObstacle(initialCircle: Circle2D, - initialRoute: DubinsPath.Type, - finalCircle: Circle2D, - obstacle: DubinsObstacle): MutableList { - val dubinsTangents = mutableListOf() - var tangent = obstacle.nextTangent(initialCircle, initialRoute) - dubinsTangents.add(tangent) - while (tangent.endCircle != finalCircle) { - tangent = obstacle.nextTangent(tangent.endCircle, initialRoute) - dubinsTangents.add(tangent) - } - return dubinsTangents -} - -private fun allFinished(paths: List>, - finalObstacle: DubinsObstacle): Boolean { - for (path in paths) { - if (path.last().endObstacle != finalObstacle) { - return false - } - } - return true -} - -public fun pathLength(path: List): Double { - val tangentsLength = path.sumOf{norm(it.lineSegment.end - it.lineSegment.begin)} - val arcsLength = buildList{ - for (i in 1..path.lastIndex) { - add(arcLength(path[i].startCircle, - path[i-1].lineSegment.end, - path[i].lineSegment.begin, - path[i].route[0])) - } - }.sum() - return tangentsLength + arcsLength -} - -public fun shortestPath(path: List>): List { - return path.sortedBy { pathLength(it) }[0] -} - -public typealias Path = List -public fun findAllPaths( - startingPoint: DoubleVector2D, - startingDirection: DoubleVector2D, - startingRadius: Double, - finalPoint: DoubleVector2D, - finalDirection: DoubleVector2D, - finalRadius: Double, - obstacles: List -): List> { - val initialCircles = constructTangentCircles( - startingPoint, - startingDirection, - startingRadius) - val finalCircles = constructTangentCircles( - finalPoint, - finalDirection, - finalRadius) - var path = mutableMapOf>>() - for (i in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { - for (j in listOf(DubinsPath.SimpleType.L, DubinsPath.SimpleType.R)) { - val finalCircle = finalCircles[j]!! - val finalObstacle = DubinsObstacle(listOf(finalCircle)) - path[listOf(i, - DubinsPath.SimpleType.S, - j)] = mutableListOf( - mutableListOf(DubinsTangent( - initialCircles[i]!!, - initialCircles[i]!!, - DubinsObstacle(listOf(initialCircles[i]!!)), - DubinsObstacle(listOf(initialCircles[i]!!)), - LineSegment2D(startingPoint, startingPoint), - listOf(i, DubinsPath.SimpleType.S, i) - ))) - //var currentObstacle = DubinsObstacle(listOf(initialCircles[i]!!)) - while (!allFinished(path[listOf(i, - DubinsPath.SimpleType.S, - j)]!!, finalObstacle)) { - var newPaths = mutableListOf>() - for (line in path[listOf(i, - DubinsPath.SimpleType.S, - j)]!!) { - var currentCircle = line.last().endCircle - var currentDirection = line.last().route.last() - var currentObstacle = line.last().endObstacle - var nextObstacle: DubinsObstacle? = null - if (currentObstacle != finalObstacle) { - var tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.toType(listOf( - currentDirection, - DubinsPath.SimpleType.S, - j) - )] - for (obstacle in sortedObstacles(currentObstacle, obstacles)) { - if (tangentToFinal!!.intersectObstacle(obstacle)) { - nextObstacle = obstacle - break - } - } - if (nextObstacle == null) { - nextObstacle = finalObstacle - } - var nextTangents = outerTangents(currentObstacle, nextObstacle) - - for (pathType in DubinsPath.Type.values()) { - for (obstacle in obstacles) { - // in Python code here try/except was used, but seems unneeded - if (nextTangents.containsKey(pathType)) { - if (nextTangents[pathType]!!.intersectObstacle(obstacle)) { - nextTangents.remove(pathType) - } - } - } - } - nextTangents = if (nextObstacle == finalObstacle) { - nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection) and - (DubinsPath.toSimpleTypes(it.key)[2] == j)} - as MutableMap - } else { - nextTangents.filter {(DubinsPath.toSimpleTypes(it.key)[0] == currentDirection)} - as MutableMap - } - var tangentsAlong = mutableListOf() - for (tangent in nextTangents.values) { - if (tangent.startCircle == line.last().endCircle) { - val lengthMaxPossible = arcLength( - tangent.startCircle, - line.last().lineSegment.end, - tangent.startObstacle.nextTangent( - tangent.startCircle, - DubinsPath.toType(listOf(currentDirection, DubinsPath.SimpleType.S, currentDirection)), - ).lineSegment.begin, - currentDirection - ) - val lengthCalculated = arcLength( - tangent.startCircle, - line.last().lineSegment.end, - tangent.lineSegment.begin, - currentDirection) - if (lengthCalculated > lengthMaxPossible) { - tangentsAlong = tangentsAlongTheObstacle( - currentCircle, - DubinsPath.toType(listOf( - currentDirection, - DubinsPath.SimpleType.S, - currentDirection)), - tangent.startCircle, - currentObstacle - ) - } - else { - tangentsAlong = mutableListOf() - } - } - else { - tangentsAlong = tangentsAlongTheObstacle( - currentCircle, - DubinsPath.toType(listOf( - currentDirection, - DubinsPath.SimpleType.S, - currentDirection)), - tangent.startCircle, - currentObstacle - ) - } - newPaths.add((line + tangentsAlong + listOf(tangent)).toMutableList()) - } - path[listOf( - i, - DubinsPath.SimpleType.S, - j - )] = newPaths - } - else { - // minor changes from Python code - newPaths.add(line) - path[listOf( - i, - DubinsPath.SimpleType.S, - j - )] = newPaths - } - } - path[listOf( - i, - DubinsPath.SimpleType.S, - j - )] = newPaths - } - for (lineId in path[listOf( - i, - DubinsPath.SimpleType.S, - j - )]!!.indices) { - val lastDirection = path[listOf( - i, - DubinsPath.SimpleType.S, - j - )]!![lineId].last().route[2] - path[listOf( - i, - DubinsPath.SimpleType.S, - j - )]!![lineId].add(DubinsTangent( - finalCircles[j]!!, - finalCircles[j]!!, - DubinsObstacle( - listOf(finalCircles[j]!!) - ), - DubinsObstacle( - listOf(finalCircles[j]!!) - ), - LineSegment2D(finalPoint, finalPoint), - listOf( - lastDirection, - DubinsPath.SimpleType.S, - j - ) - )) - } - } - } - return path[listOf( - DubinsPath.SimpleType.L, - DubinsPath.SimpleType.S, - DubinsPath.SimpleType.L - )]!! + path[listOf( - DubinsPath.SimpleType.L, - DubinsPath.SimpleType.S, - DubinsPath.SimpleType.R - )]!! + path[listOf( - DubinsPath.SimpleType.R, - DubinsPath.SimpleType.S, - DubinsPath.SimpleType.L - )]!! + path[listOf( - DubinsPath.SimpleType.R, - DubinsPath.SimpleType.S, - DubinsPath.SimpleType.R)]!! -} - - - - - - - - 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 index 5654d10ae..272cf9e5b 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -7,6 +7,8 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.* import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.trajectory.Trajectory2D.Type +import space.kscience.kmath.trajectory.Trajectory2D.Type.* import kotlin.math.acos internal fun DubinsPose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first @@ -19,27 +21,21 @@ internal fun DubinsPose2D.getTangentCircles(radius: Double): Pair vector( - a.center.x - a.radius * cos(centers.bearing), - a.center.y + a.radius * sin(centers.bearing) + val centers = StraightTrajectory2D(from.center, to.center) + val p1 = when (direction) { + L -> vector( + from.center.x - from.radius * cos(centers.bearing), + from.center.y + from.radius * sin(centers.bearing) ) - CircleTrajectory2D.Direction.RIGHT -> vector( - a.center.x + a.radius * cos(centers.bearing), - a.center.y - a.radius * sin(centers.bearing) + R -> vector( + from.center.x + from.radius * cos(centers.bearing), + from.center.y - from.radius * sin(centers.bearing) ) + + else -> error("S trajectory type not allowed") } return StraightTrajectory2D( p1, @@ -47,29 +43,25 @@ private fun outerTangent(a: Circle2D, b: Circle2D, side: CircleTrajectory2D.Dire ) } -internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory2D? = - innerTangent(base, direction, CircleTrajectory2D.Direction.LEFT) - -internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightTrajectory2D? = - innerTangent(base, direction, CircleTrajectory2D.Direction.RIGHT) private fun innerTangent( - base: Circle2D, - direction: Circle2D, - side: CircleTrajectory2D.Direction, + from: Circle2D, + to: Circle2D, + direction: Type, ): StraightTrajectory2D? = with(Euclidean2DSpace) { - val centers = StraightTrajectory2D(base.center, direction.center) - if (centers.length < base.radius * 2) return null - val angle = when (side) { - CircleTrajectory2D.Direction.LEFT -> centers.bearing + acos(base.radius * 2 / centers.length).radians - CircleTrajectory2D.Direction.RIGHT -> centers.bearing - acos(base.radius * 2 / centers.length).radians + val centers = StraightTrajectory2D(from.center, to.center) + if (centers.length < from.radius * 2) return null + val angle = when (direction) { + L -> centers.bearing + acos(from.radius * 2 / centers.length).radians + R -> centers.bearing - acos(from.radius * 2 / centers.length).radians + else -> error("S trajectory type not allowed") }.normalized() - 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) + val dX = from.radius * sin(angle) + val dY = from.radius * cos(angle) + val p1 = vector(from.center.x + dX, from.center.y + dY) + val p2 = vector(to.center.x - dX, to.center.y - dY) return StraightTrajectory2D(p1, p2) } @@ -77,118 +69,25 @@ private fun innerTangent( @Suppress("DuplicatedCode") public object DubinsPath { -// public class ArcType(private val type: Type){ -// public val first: SimpleType -// get() { -// if (this.type in listOf(Type.RSR, Type.RSL, Type.RLR)) { -// return SimpleType.R -// } -// else if (type in listOf(Type.LSL, Type.LSR, Type.LRL)) { -// return SimpleType.L -// } -// error("Wrong DubinsPath.Type") -// } -// -// public val last: SimpleType -// get() { -// if (type in listOf(Type.RSR, Type.LSR, Type.RLR)) { -// return SimpleType.R -// } -// else if (type in listOf(Type.LSL, Type.RSL, Type.LRL)) { -// return SimpleType.L -// } -// error("Wrong DubinsPath.Type") -// } -// public val intermediate: SimpleType -// get() { -// if (type == Type.RLR) { -// return SimpleType.L -// } -// else if (type == Type.LRL) { -// return SimpleType.R -// } -// error("This DubinsPath.Type doesn't contain intermediate arc") -// } -// } + public data class Type( + public val first: Trajectory2D.Type, + public val second: Trajectory2D.Type, + public val third: Trajectory2D.Type, + ) { + public fun toList(): List = listOf(first, second, third) - public enum class SimpleType { - R, S, L - } + override fun toString(): String = "${first.name}${second.name}${third.name}" - public enum class Type { - RLR, LRL, RSR, LSL, RSL, LSR - } - - public fun toSimpleTypes(type: Type): List { - when (type) { - Type.RLR -> { - return listOf(SimpleType.R, SimpleType.L, SimpleType.R) - } - Type.LRL -> { - return listOf(SimpleType.L, SimpleType.R, SimpleType.L) - } - Type.RSR -> { - return listOf(SimpleType.R, SimpleType.S, SimpleType.R) - } - Type.LSL -> { - return listOf(SimpleType.L, SimpleType.S, SimpleType.L) - } - Type.RSL -> { - return listOf(SimpleType.R, SimpleType.S, SimpleType.L) - } - Type.LSR -> { - return listOf(SimpleType.L, SimpleType.S, SimpleType.R) - } - else -> error("This type doesn't exist") + public companion object { + public val RLR: Type = Type(R, L, R) + public val LRL: Type = Type(L, R, L) + public val RSR: Type = Type(R, S, R) + public val LSL: Type = Type(L, S, L) + public val RSL: Type = Type(R, S, L) + public val LSR: Type = Type(L, S, R) } } - public fun toType(types: List): Type { - when (types) { - listOf(SimpleType.R, SimpleType.L, SimpleType.R) -> { - return Type.RLR - } - listOf(SimpleType.L, SimpleType.R, SimpleType.L) -> { - return Type.LRL - } - listOf(SimpleType.R, SimpleType.S, SimpleType.R) -> { - return Type.RSR - } - listOf(SimpleType.L, SimpleType.S, SimpleType.L) -> { - return Type.LSL - } - listOf(SimpleType.R, SimpleType.S, SimpleType.L) -> { - return Type.RSL - } - listOf(SimpleType.L, SimpleType.S, SimpleType.R) -> { - return Type.LSR - } - else -> error("This type doesn't exist") - } - } - -// public class PathTypes(private val inputTypes: List) { -// public val type: Type -// get() { -// when (this.inputTypes) { -// listOf(SimpleType.R, SimpleType.S, SimpleType.R) -> { -// return Type.RSR -// } -// listOf(SimpleType.R, SimpleType.S, SimpleType.L) -> { -// return Type.RSL -// } -// listOf(SimpleType.L, SimpleType.S, SimpleType.R) -> { -// return Type.LSR -// } -// listOf(SimpleType.L, SimpleType.S, SimpleType.L) -> { -// return Type.LSL -// } -// else -> error("Wrong list of SimpleTypes") -// } -// } -// public val chain: List = this.inputTypes -// } - /** * Return Dubins trajectory type or null if trajectory is not a Dubins path */ @@ -197,12 +96,10 @@ public object DubinsPath { val a = trajectory2D.segments.first() as? CircleTrajectory2D ?: return null val b = trajectory2D.segments[1] val c = trajectory2D.segments.last() as? CircleTrajectory2D ?: return null - return Type.valueOf( - arrayOf( - a.direction.name[0], - if (b is CircleTrajectory2D) b.direction.name[0] else 'S', - c.direction.name[0] - ).toCharArray().concatToString() + return Type( + a.direction, + if (b is CircleTrajectory2D) b.direction else Trajectory2D.Type.S, + c.direction ) } @@ -240,9 +137,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.R) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.L) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.R) CompositeTrajectory2D(a1, a2, a3) } @@ -257,9 +154,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.RIGHT) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.R) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.L) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.R) CompositeTrajectory2D(a1, a2, a3) } @@ -284,9 +181,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.L) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.R) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.L) CompositeTrajectory2D(a1, a2, a3) } @@ -301,9 +198,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, CircleTrajectory2D.Direction.LEFT) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, CircleTrajectory2D.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.L) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.R) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.L) CompositeTrajectory2D(a1, a2, a3) } @@ -313,45 +210,45 @@ public object DubinsPath { public fun rsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) - val s = leftOuterTangent(c1, c2) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) + val s = outerTangent(c1, c2, L) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.R) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.R) return CompositeTrajectory2D(a1, s, a3) } public fun lsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) - val s = rightOuterTangent(c1, c2) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) + val s = outerTangent(c1, c2, R) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.L) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.L) return CompositeTrajectory2D(a1, s, a3) } public fun rsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { val c1 = start.getRightCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) - val s = rightInnerTangent(c1, c2) + val s = innerTangent(c1, c2, R) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.RIGHT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.LEFT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.R) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.L) return CompositeTrajectory2D(a1, s, a3) } public fun lsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) - val s = leftInnerTangent(c1, c2) + val s = innerTangent(c1, c2, L) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, CircleTrajectory2D.Direction.LEFT) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, CircleTrajectory2D.Direction.RIGHT) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.L) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.R) return CompositeTrajectory2D(a1, s, a3) } } -public typealias PathTypes = List +public typealias PathTypes = List public fun interface MaxCurvature { public fun compute(startPoint: PhaseVector2D): Double diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt new file mode 100644 index 000000000..d5d04e1a4 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -0,0 +1,619 @@ +/* + * Copyright 2018-2023 KMath 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.* +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Euclidean2DSpace.minus +import space.kscience.kmath.geometry.Euclidean2DSpace.norm +import space.kscience.kmath.geometry.Euclidean2DSpace.plus +import space.kscience.kmath.geometry.Euclidean2DSpace.times +import space.kscience.kmath.geometry.Euclidean2DSpace.vector +import space.kscience.kmath.operations.DoubleField.pow +import kotlin.math.* + +internal data class Tangent( + val startCircle: Circle2D, + val endCircle: Circle2D, + val startObstacle: Obstacle, + val endObstacle: Obstacle, + val lineSegment: LineSegment2D, + val trajectoryType: List, +) + +private class TangentPath(val tangents: List) { + fun last() = tangents.last() +} + +private fun TangentPath(vararg tangents: Tangent) = TangentPath(listOf(*tangents)) + +/** + * Create inner and outer tangents between two circles. + * This method returns a map of segments using [DubinsPath] connection type notation. + */ +internal fun Circle2D.tangentsToCircle( + other: Circle2D, +): Map = with(Euclidean2DSpace) { + //return empty map for concentric circles + if (center.equalsVector(other.center)) return emptyMap() + + // A line connecting centers + val line = LineSegment(center, other.center) + // Distance between centers + val distance = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(radius, other.radius), + DubinsPath.Type.RSL to Pair(radius, -other.radius), + DubinsPath.Type.LSR to Pair(-radius, other.radius), + DubinsPath.Type.LSL to Pair(-radius, -other.radius) + ) + return buildMap { + for ((route, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + val r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (distance * distance >= r * r) { + val l = sqrt(distance * distance - r * r) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + put( + route, + LineSegment( + center + w * r1, + other.center + w * r2 + ) + ) + } else { + throw Exception("Circles should not intersect") + } + } + } +} + +private fun dubinsTangentsToCircles( + firstCircle: Circle2D, + secondCircle: Circle2D, + firstObstacle: Obstacle, + secondObstacle: Obstacle, +): Map = with(Euclidean2DSpace) { + val line = LineSegment(firstCircle.center, secondCircle.center) + val distance = line.begin.distanceTo(line.end) + val angle1 = atan2( + secondCircle.center.x - firstCircle.center.x, + secondCircle.center.y - firstCircle.center.y + ) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(firstCircle.radius, secondCircle.radius), + DubinsPath.Type.RSL to Pair(firstCircle.radius, -secondCircle.radius), + DubinsPath.Type.LSR to Pair(-firstCircle.radius, secondCircle.radius), + DubinsPath.Type.LSL to Pair(-firstCircle.radius, -secondCircle.radius) + ) + return buildMap { + for ((route: DubinsPath.Type, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (distance * distance >= r * r) { + val l = sqrt(distance * distance - r * r) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put( + route, + Tangent( + startCircle = Circle2D(firstCircle.center, firstCircle.radius), + endCircle = secondCircle, + startObstacle = firstObstacle, + endObstacle = secondObstacle, + lineSegment = LineSegment2D( + firstCircle.center + w * r1, + secondCircle.center + w * r2 + ), + trajectoryType = route.toList() + ) + ) + } else { + throw Exception("Circles should not intersect") + } + } + } +} + +public class Obstacle( + public val circles: List, +) { + internal val tangents: List = boundaryTangents().first + public val boundaryRoute: DubinsPath.Type = boundaryTangents().second + + public val center: Vector2D = vector( + circles.sumOf { it.center.x } / circles.size, + circles.sumOf { it.center.y } / circles.size + ) + + private fun boundaryTangents(): Pair, DubinsPath.Type> { + // outer tangents for a polygon circles can be either lsl or rsr + + fun Circle2D.dubinsTangentsToCircles( + other: Circle2D, + ): Map = with(Euclidean2DSpace) { + val line = LineSegment(center, other.center) + val d = line.begin.distanceTo(line.end) + val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) + var r: Double + var angle2: Double + val routes = mapOf( + DubinsPath.Type.RSR to Pair(radius, other.radius), + DubinsPath.Type.LSL to Pair(-radius, -other.radius) + ) + return buildMap { + for ((routeType, r1r2) in routes) { + val r1 = r1r2.first + val r2 = r1r2.second + r = if (r1.sign == r2.sign) { + r1.absoluteValue - r2.absoluteValue + } else { + r1.absoluteValue + r2.absoluteValue + } + if (d * d >= r * r) { + val l = (d * d - r * r).pow(0.5) + angle2 = if (r1.absoluteValue > r2.absoluteValue) { + angle1 + r1.sign * atan2(r.absoluteValue, l) + } else { + angle1 - r2.sign * atan2(r.absoluteValue, l) + } + val w = vector(-cos(angle2), sin(angle2)) + put( + routeType, Tangent( + Circle2D(center, radius), + other, + this@Obstacle, + this@Obstacle, + LineSegment2D( + center + w * r1, + other.center + w * r2 + ), + routeType.toList() + ) + ) + } else { + throw Exception("Circles should not intersect") + } + } + } + } + + val firstCircles = circles + val secondCircles = circles.slice(1..circles.lastIndex) + + circles[0] + val lslTangents = firstCircles.zip(secondCircles) + { a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.LSL]!! } + val rsrTangents = firstCircles.zip(secondCircles) + { a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.RSR]!! } + val center = vector( + circles.sumOf { it.center.x } / circles.size, + circles.sumOf { it.center.y } / circles.size + ) + val lslToCenter = lslTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + + lslTangents.sumOf { it.lineSegment.end.distanceTo(center) } + val rsrToCenter = rsrTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + + rsrTangents.sumOf { it.lineSegment.end.distanceTo(center) } + return if (rsrToCenter >= lslToCenter) { + Pair(rsrTangents, DubinsPath.Type.RSR) + } else { + Pair(lslTangents, DubinsPath.Type.LSL) + } + } + + override fun equals(other: Any?): Boolean { + if (other == null || other !is Obstacle) return false + return circles == other.circles + } + + override fun hashCode(): Int { + return circles.hashCode() + } +} + +private fun Obstacle.nextTangent(circle: Circle2D, routeType: DubinsPath.Type): Tangent { + if (routeType == boundaryRoute) { + for (i in circles.indices) { + if (circles[i] == circle) { + return tangents[i] + } + } + } else { + for (i in circles.indices) { + if (circles[i] == circle) { + if (i > 0) { + return Tangent( + circles[i], + circles[i - 1], + this, + this, + LineSegment2D( + tangents[i - 1].lineSegment.end, + tangents[i - 1].lineSegment.begin + ), + routeType.toList() + ) + } else { + return Tangent( + circles[0], + circles.last(), + this, + this, + LineSegment2D( + tangents.last().lineSegment.end, + tangents.last().lineSegment.begin + ), + routeType.toList() + ) + } + } + } + } + + error("next tangent not found") +} + +public fun Obstacle(vararg circles: Circle2D): Obstacle = Obstacle(listOf(*circles)) + +private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { + fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { + return v1.x * v2.y - v1.y * v2.x + } + return if (crossProduct(other.begin - begin, other.end - begin).sign == + crossProduct(other.begin - end, other.end - end).sign + ) { + false + } else { + crossProduct(begin - other.begin, end - other.begin).sign != crossProduct( + begin - other.end, + end - other.end + ).sign + } +} + +private fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { + val a = (begin.x - end.x).pow(2.0) + (begin.y - end.y).pow(2.0) + val b = 2 * ((begin.x - end.x) * (end.x - circle.center.x) + + (begin.y - end.y) * (end.y - circle.center.y)) + val c = (end.x - circle.center.x).pow(2.0) + (end.y - circle.center.y).pow(2.0) - + circle.radius.pow(2.0) + val d = b.pow(2.0) - 4 * a * c + if (d < 1e-6) { + return false + } else { + val t1 = (-b - d.pow(0.5)) * 0.5 / a + val t2 = (-b + d.pow(0.5)) * 0.5 / a + if (((0 < t1) and (t1 < 1)) or ((0 < t2) and (t2 < 1))) { + return true + } + } + return false +} + +private fun Tangent.intersectObstacle(obstacle: Obstacle): Boolean { + for (tangent in obstacle.tangents) { + if (lineSegment.intersectSegment(tangent.lineSegment)) { + return true + } + } + for (circle in obstacle.circles) { + if (lineSegment.intersectCircle(circle)) { + return true + } + } + return false +} + +private fun outerTangents(first: Obstacle, second: Obstacle): Map = buildMap { + for (circle1 in first.circles) { + for (circle2 in second.circles) { + for (tangent in dubinsTangentsToCircles(circle1, circle2, first, second)) { + if (!(tangent.value.intersectObstacle(first)) + and !(tangent.value.intersectObstacle(second)) + ) { + put( + tangent.key, + tangent.value + ) + } + } + } + } +} + +private fun arcLength( + circle: Circle2D, + point1: DoubleVector2D, + point2: DoubleVector2D, + route: Trajectory2D.Type, +): Double { + val phi1 = atan2(point1.y - circle.center.y, point1.x - circle.center.x) + val phi2 = atan2(point2.y - circle.center.y, point2.x - circle.center.x) + var angle = 0.0 + when (route) { + Trajectory2D.Type.L -> { + angle = if (phi2 >= phi1) { + phi2 - phi1 + } else { + 2 * PI + phi2 - phi1 + } + } + + Trajectory2D.Type.R -> { + angle = if (phi2 >= phi1) { + 2 * PI - (phi2 - phi1) + } else { + -(phi2 - phi1) + } + } + + Trajectory2D.Type.S -> { + error("L or R route is expected") + } + } + return circle.radius * angle +} + +private fun normalVectors(v: DoubleVector2D, r: Double): Pair { + return Pair( + r * vector(v.y / norm(v), -v.x / norm(v)), + r * vector(-v.y / norm(v), v.x / norm(v)) + ) +} + +private fun constructTangentCircles( + point: DoubleVector2D, + direction: DoubleVector2D, + r: Double, +): Map { + val center1 = point + normalVectors(direction, r).first + val center2 = point + normalVectors(direction, r).second + val p1 = center1 - point + return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI / 2, -3 * PI / 2)) { + mapOf( + Trajectory2D.Type.L to Circle2D(center1, r), + Trajectory2D.Type.R to Circle2D(center2, r) + ) + } else { + mapOf( + Trajectory2D.Type.L to Circle2D(center2, r), + Trajectory2D.Type.R to Circle2D(center1, r) + ) + } +} + +private fun sortedObstacles( + currentObstacle: Obstacle, + obstacles: List, +): List { + return obstacles.sortedBy { norm(it.center - currentObstacle.center) }//.reversed() +} + +private fun tangentsAlongTheObstacle( + initialCircle: Circle2D, + initialRoute: DubinsPath.Type, + finalCircle: Circle2D, + obstacle: Obstacle, +): List { + val dubinsTangents = mutableListOf() + var tangent = obstacle.nextTangent(initialCircle, initialRoute) + dubinsTangents.add(tangent) + while (tangent.endCircle != finalCircle) { + tangent = obstacle.nextTangent(tangent.endCircle, initialRoute) + dubinsTangents.add(tangent) + } + return dubinsTangents +} + +private fun allFinished( + paths: List, + finalObstacle: Obstacle, +): Boolean { + for (path in paths) { + if (path.last().endObstacle != finalObstacle) { + return false + } + } + return true +} + +private fun LineSegment2D.toTrajectory() = StraightTrajectory2D(begin, end) + + +private fun TangentPath.toTrajectory(): CompositeTrajectory2D = CompositeTrajectory2D( + buildList { + tangents.zipWithNext().forEach { (left, right) -> + add(left.lineSegment.toTrajectory()) + add( + CircleTrajectory2D.of( + right.startCircle.center, + left.lineSegment.end, + right.lineSegment.begin, + right.trajectoryType.first() + ) + ) + } + + add(tangents.last().lineSegment.toTrajectory()) + } +) + +internal fun findAllPaths( + startingPoint: DoubleVector2D, + startingDirection: DoubleVector2D, + startingRadius: Double, + finalPoint: DoubleVector2D, + finalDirection: DoubleVector2D, + finalRadius: Double, + obstacles: List, +): List { + val initialCircles = constructTangentCircles( + startingPoint, + startingDirection, + startingRadius + ) + val finalCircles = constructTangentCircles( + finalPoint, + finalDirection, + finalRadius + ) + val trajectories = mutableListOf() + for (i in listOf(Trajectory2D.Type.L, Trajectory2D.Type.R)) { + for (j in listOf(Trajectory2D.Type.L, Trajectory2D.Type.R)) { + val finalCircle = finalCircles[j]!! + val finalObstacle = Obstacle(listOf(finalCircle)) + var currentPaths: List = listOf( + TangentPath( + Tangent( + initialCircles[i]!!, + initialCircles[i]!!, + Obstacle(listOf(initialCircles[i]!!)), + Obstacle(listOf(initialCircles[i]!!)), + LineSegment2D(startingPoint, startingPoint), + listOf(i, Trajectory2D.Type.S, i) + ) + ) + ) + while (!allFinished(currentPaths, finalObstacle)) { + val newPaths = mutableListOf() + for (tangentPath: TangentPath in currentPaths) { + val currentCircle = tangentPath.last().endCircle + val currentDirection = tangentPath.last().trajectoryType.last() + val currentObstacle = tangentPath.last().endObstacle + var nextObstacle: Obstacle? = null + if (currentObstacle != finalObstacle) { + val tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.Type( + currentDirection, + Trajectory2D.Type.S, + j + )] + for (obstacle in sortedObstacles(currentObstacle, obstacles)) { + if (tangentToFinal!!.intersectObstacle(obstacle)) { + nextObstacle = obstacle + break + } + } + if (nextObstacle == null) { + nextObstacle = finalObstacle + } + val nextTangents: Map = outerTangents(currentObstacle, nextObstacle) + .filter { (key, tangent) -> + obstacles.none { obstacle -> tangent.intersectObstacle(obstacle) } && + key.first == currentDirection && + (nextObstacle != finalObstacle || key.third == j) + } + + var tangentsAlong: List + for (tangent in nextTangents.values) { + if (tangent.startCircle == tangentPath.last().endCircle) { + val lengthMaxPossible = arcLength( + tangent.startCircle, + tangentPath.last().lineSegment.end, + tangent.startObstacle.nextTangent( + tangent.startCircle, + DubinsPath.Type( + currentDirection, + Trajectory2D.Type.S, + currentDirection + ), + ).lineSegment.begin, + currentDirection + ) + val lengthCalculated = arcLength( + tangent.startCircle, + tangentPath.last().lineSegment.end, + tangent.lineSegment.begin, + currentDirection + ) + tangentsAlong = if (lengthCalculated > lengthMaxPossible) { + tangentsAlongTheObstacle( + currentCircle, + DubinsPath.Type( + currentDirection, + Trajectory2D.Type.S, + currentDirection + ), + tangent.startCircle, + currentObstacle + ) + } else { + emptyList() + } + } else { + tangentsAlong = tangentsAlongTheObstacle( + currentCircle, + DubinsPath.Type( + currentDirection, + Trajectory2D.Type.S, + currentDirection + ), + tangent.startCircle, + currentObstacle + ) + } + newPaths.add(TangentPath(tangentPath.tangents + tangentsAlong + tangent)) + } + } else { + // minor changes from Python code + newPaths.add(tangentPath) + } + } + currentPaths = newPaths + } + + trajectories += currentPaths.map { tangentPath -> + val lastDirection: Trajectory2D.Type = tangentPath.last().trajectoryType[2] + val end = finalCircles[j]!! + TangentPath( + tangentPath.tangents + + Tangent( + end, + end, + Obstacle(end), + Obstacle(end), + LineSegment2D(finalPoint, finalPoint), + listOf( + lastDirection, + Trajectory2D.Type.S, + j + ) + ) + ) + }.map { it.toTrajectory() } + } + } + return trajectories +} + + + + + + + + diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index e5f60e025..7bf17fc26 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -16,6 +16,12 @@ import kotlin.math.atan2 @Serializable public sealed interface Trajectory2D { public val length: Double + + public enum class Type { + R, + S, + L + } } /** @@ -27,11 +33,14 @@ public data class StraightTrajectory2D( public val start: DoubleVector2D, public val end: DoubleVector2D, ) : Trajectory2D { + override val length: Double get() = start.distanceTo(end) public val bearing: Angle get() = (atan2(end.x - start.x, end.y - start.y).radians).normalized() } +public fun StraightTrajectory2D.toSegment(): LineSegment> = LineSegment2D(start, end) + /** * An arc segment */ @@ -43,15 +52,11 @@ public data class CircleTrajectory2D( public val end: DubinsPose2D, ) : Trajectory2D { - public enum class Direction { - LEFT, RIGHT - } - /** * Arc length in radians */ val arcLength: Angle - get() = if (direction == Direction.LEFT) { + get() = if (direction == Trajectory2D.Type.L) { start.bearing - end.bearing } else { end.bearing - start.bearing @@ -62,16 +67,16 @@ public data class CircleTrajectory2D( circle.radius * arcLength.radians } - public val direction: Direction by lazy { + public val direction: Trajectory2D.Type by lazy { if (start.y < circle.center.y) { - if (start.bearing > Angle.pi) Direction.RIGHT else Direction.LEFT + if (start.bearing > Angle.pi) Trajectory2D.Type.R else Trajectory2D.Type.L } else if (start.y > circle.center.y) { - if (start.bearing < Angle.pi) Direction.RIGHT else Direction.LEFT + if (start.bearing < Angle.pi) Trajectory2D.Type.R else Trajectory2D.Type.L } else { if (start.bearing == Angle.zero) { - if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT + if (start.x < circle.center.x) Trajectory2D.Type.R else Trajectory2D.Type.L } else { - if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + if (start.x > circle.center.x) Trajectory2D.Type.R else Trajectory2D.Type.L } } } @@ -81,17 +86,18 @@ public data class CircleTrajectory2D( center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, - direction: Direction, + direction: Trajectory2D.Type, ): CircleTrajectory2D { fun calculatePose( vector: DoubleVector2D, theta: Angle, - direction: Direction, + direction: Trajectory2D.Type, ): DubinsPose2D = DubinsPose2D( vector, when (direction) { - Direction.LEFT -> (theta - Angle.piDiv2).normalized() - Direction.RIGHT -> (theta + Angle.piDiv2).normalized() + Trajectory2D.Type.L -> (theta - Angle.piDiv2).normalized() + Trajectory2D.Type.R -> (theta + Angle.piDiv2).normalized() + else -> error("S trajectory type is not allowed in circle constructor") } ) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt deleted file mode 100644 index fb1c3927b..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/tangent.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.* -import kotlin.math.* - -/** - * Create inner and outer tangents between two circles. - * This method returns a map of segments using [DubinsPath] connection type notation. - */ -public fun Circle2D.tangentsToCircle( - other: Circle2D, -): Map> = with(Euclidean2DSpace) { - //return empty map for concentric circles - if(center.equalsVector(other.center)) return@tangentsToCircle emptyMap() - - // A line connecting centers - val line = LineSegment(center, other.center) - // Distance between centers - val distance = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(radius, other.radius), - DubinsPath.Type.RSL to Pair(radius, -other.radius), - DubinsPath.Type.LSR to Pair(-radius, other.radius), - DubinsPath.Type.LSL to Pair(-radius, -other.radius) - ) - return buildMap { - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - val r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (distance * distance >= r * r) { - val l = sqrt(distance * distance - r * r) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) - put( - route, - LineSegment( - center + w * r1, - other.center + w * r2 - ) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } -} - -public fun dubinsTangentsToCircles( - firstCircle: Circle2D, - secondCircle: Circle2D, - firstObstacle: DubinsObstacle, - secondObstacle: DubinsObstacle -): Map = with(Euclidean2DSpace) { - val line = LineSegment(firstCircle.center, secondCircle.center) - val distance = line.begin.distanceTo(line.end) - val angle1 = atan2(secondCircle.center.x - firstCircle.center.x, - secondCircle.center.y - firstCircle.center.y) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(firstCircle.radius, secondCircle.radius), - DubinsPath.Type.RSL to Pair(firstCircle.radius, -secondCircle.radius), - DubinsPath.Type.LSR to Pair(-firstCircle.radius, secondCircle.radius), - DubinsPath.Type.LSL to Pair(-firstCircle.radius, -secondCircle.radius) - ) - return buildMap { - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (distance * distance >= r * r) { - val l = sqrt(distance * distance - r * r) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put(route, DubinsTangent(Circle2D(firstCircle.center, firstCircle.radius), - secondCircle, - firstObstacle, - secondObstacle, - LineSegment2D( - firstCircle.center + w * r1, - secondCircle.center + w * r2 - ), - DubinsPath.toSimpleTypes(route)) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } -} \ No newline at end of file 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/DubinsTests.kt similarity index 93% rename from kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt rename to kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt index 481ea4786..f5bfb884e 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt @@ -1,13 +1,12 @@ /* - * Copyright 2018-2022 KMath contributors. + * Copyright 2018-2023 KMath 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 +package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.equalsFloat -import space.kscience.kmath.trajectory.* import kotlin.test.Test import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -37,7 +36,7 @@ class DubinsTests { ) expectedLengths.forEach { - val path = dubins.find { p -> DubinsPath.trajectoryTypeOf(p) === it.key } + val path = dubins.find { p -> DubinsPath.trajectoryTypeOf(p) == it.key } assertNotNull(path, "Path ${it.key} not found") println("${it.key}: ${path.length}") assertTrue(it.value.equalsFloat(path.length)) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt similarity index 55% rename from kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt rename to kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt index 07e9861c7..446e0a4d3 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt @@ -7,12 +7,10 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.geometry.equalsFloat import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue -class DubinsTest { +class ObstacleTest { @Test fun firstPath() { val startPoint = vector(-5.0, -1.0) @@ -22,8 +20,13 @@ class DubinsTest { val finalDirection = vector(1.0, -1.0) val finalRadius = 0.5 - val obstacles = listOf(DubinsObstacle(listOf( - Circle2D(vector(7.0, 1.0), 5.0)))) + val obstacles = listOf( + Obstacle( + listOf( + Circle2D(vector(7.0, 1.0), 5.0) + ) + ) + ) val outputTangents = findAllPaths( startPoint, @@ -32,8 +35,9 @@ class DubinsTest { finalPoint, finalDirection, finalRadius, - obstacles) - val length = pathLength(shortestPath(outputTangents)) + obstacles + ) + val length = outputTangents.minOf { it.length } assertEquals(length, 27.2113183, 1e-6) } @@ -47,17 +51,21 @@ class DubinsTest { val finalRadius = 0.5 val obstacles = listOf( - DubinsObstacle(listOf( - Circle2D(vector(1.0, 6.5), 0.5), - Circle2D(vector(2.0, 1.0), 0.5), - Circle2D(vector(6.0, 0.0), 0.5), - Circle2D(vector(5.0, 5.0), 0.5) - )), DubinsObstacle(listOf( - Circle2D(vector(10.0, 1.0), 0.5), - Circle2D(vector(16.0, 0.0), 0.5), - Circle2D(vector(14.0, 6.0), 0.5), - Circle2D(vector(9.0, 4.0), 0.5) - )) + Obstacle( + listOf( + Circle2D(vector(1.0, 6.5), 0.5), + Circle2D(vector(2.0, 1.0), 0.5), + Circle2D(vector(6.0, 0.0), 0.5), + Circle2D(vector(5.0, 5.0), 0.5) + ) + ), Obstacle( + listOf( + Circle2D(vector(10.0, 1.0), 0.5), + Circle2D(vector(16.0, 0.0), 0.5), + Circle2D(vector(14.0, 6.0), 0.5), + Circle2D(vector(9.0, 4.0), 0.5) + ) + ) ) val paths = findAllPaths( startPoint, @@ -66,22 +74,19 @@ class DubinsTest { finalPoint, finalDirection, finalRadius, - obstacles) - val length = pathLength(shortestPath(paths)) - assertEquals(length,28.9678224, 1e-6) - } - @Test - fun equalCircles() { - val circle1 = Circle2D(vector(1.0, 6.5), 0.5) - val circle2 = Circle2D(vector(1.0, 6.5), 0.5) - println(circle1 == circle2) + obstacles + ) + val length = paths.minOf { it.length } + assertEquals(length, 28.9678224, 1e-6) } + @Test fun equalObstacles() { val circle1 = Circle2D(vector(1.0, 6.5), 0.5) val circle2 = Circle2D(vector(1.0, 6.5), 0.5) - val obstacle1 = DubinsObstacle(listOf(circle1)) - val obstacle2 = DubinsObstacle(listOf(circle2)) - println(obstacle1 == obstacle2) + assertEquals(circle1, circle2) + val obstacle1 = Obstacle(listOf(circle1)) + val obstacle2 = Obstacle(listOf(circle2)) + assertEquals(obstacle1, obstacle2) } } \ No newline at end of file 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 index 7594aa046..f149004bb 100644 --- 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 @@ -10,6 +10,7 @@ import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.circumference import space.kscience.kmath.geometry.degrees import space.kscience.kmath.trajectory.CircleTrajectory2D +import space.kscience.kmath.trajectory.Trajectory2D import kotlin.test.Test import kotlin.test.assertEquals @@ -22,7 +23,7 @@ class ArcTests { circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), - CircleTrajectory2D.Direction.RIGHT + Trajectory2D.Type.R ) assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.start.bearing.degrees) From 109e050f03abc0b585a024dd8abd743aa434e8d1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 15:16:33 +0300 Subject: [PATCH 64/72] Hieraechy for trajectory types --- .../space/kscience/kmath/misc/Featured.kt | 2 +- .../space/kscience/kmath/misc/collections.kt | 22 +++++++ .../kscience/kmath/trajectory/DubinsPath.kt | 58 +++++++++---------- .../kscience/kmath/trajectory/Trajectory2D.kt | 40 ++++++++----- .../kscience/kmath/trajectory/ObstacleTest.kt | 4 +- .../kmath/trajectory/segments/ArcTests.kt | 2 +- 6 files changed, 78 insertions(+), 50 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt 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 a752a8339..bdda674dc 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 @@ -9,7 +9,7 @@ import kotlin.jvm.JvmInline import kotlin.reflect.KClass /** - * A entity that contains a set of features defined by their types + * An entity that contains a set of features defined by their types */ public interface Featured { public fun getFeature(type: FeatureKey): T? diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt new file mode 100644 index 000000000..90cc5bbfa --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2023 KMath 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 + +/** + * The same as [zipWithNext], but includes link between last and first element + */ +public inline fun List.zipWithNextCircular(transform: (a: T, b: T) -> R): List { + if (isEmpty()) return emptyList() + return indices.map { i -> + if (i == size - 1) { + transform(last(), first()) + } else { + transform(get(i), get(i + 1)) + } + } +} + +public inline fun List.zipWithNextCircular(): List> = zipWithNextCircular { l, r -> l to r } \ No newline at end of file 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 index 272cf9e5b..87ea52a69 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -7,8 +7,7 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.* import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.trajectory.Trajectory2D.Type -import space.kscience.kmath.trajectory.Trajectory2D.Type.* +import space.kscience.kmath.trajectory.Trajectory2D.* import kotlin.math.acos internal fun DubinsPose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first @@ -21,7 +20,7 @@ internal fun DubinsPose2D.getTangentCircles(radius: Double): Pair error("S trajectory type not allowed") } return StraightTrajectory2D( p1, @@ -47,7 +44,7 @@ private fun outerTangent(from: Circle2D, to: Circle2D, direction: Type): Straigh private fun innerTangent( from: Circle2D, to: Circle2D, - direction: Type, + direction: Direction, ): StraightTrajectory2D? = with(Euclidean2DSpace) { val centers = StraightTrajectory2D(from.center, to.center) @@ -55,7 +52,6 @@ private fun innerTangent( val angle = when (direction) { L -> centers.bearing + acos(from.radius * 2 / centers.length).radians R -> centers.bearing - acos(from.radius * 2 / centers.length).radians - else -> error("S trajectory type not allowed") }.normalized() val dX = from.radius * sin(angle) @@ -70,13 +66,13 @@ private fun innerTangent( public object DubinsPath { public data class Type( - public val first: Trajectory2D.Type, + public val first: Direction, public val second: Trajectory2D.Type, - public val third: Trajectory2D.Type, + public val third: Direction, ) { public fun toList(): List = listOf(first, second, third) - override fun toString(): String = "${first.name}${second.name}${third.name}" + override fun toString(): String = "${first}${second}${third}" public companion object { public val RLR: Type = Type(R, L, R) @@ -98,7 +94,7 @@ public object DubinsPath { val c = trajectory2D.segments.last() as? CircleTrajectory2D ?: return null return Type( a.direction, - if (b is CircleTrajectory2D) b.direction else Trajectory2D.Type.S, + if (b is CircleTrajectory2D) b.direction else S, c.direction ) } @@ -137,9 +133,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.R) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.L) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.R) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, R) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, L) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, R) CompositeTrajectory2D(a1, a2, a3) } @@ -154,9 +150,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.R) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.L) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.R) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, R) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, L) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, R) CompositeTrajectory2D(a1, a2, a3) } @@ -181,9 +177,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.L) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.R) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.L) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, L) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, R) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, L) CompositeTrajectory2D(a1, a2, a3) } @@ -198,9 +194,9 @@ public object DubinsPath { dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, Trajectory2D.Type.L) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, Trajectory2D.Type.R) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, Trajectory2D.Type.L) + val a1 = CircleTrajectory2D.of(c1.center, start, p1, L) + val a2 = CircleTrajectory2D.of(e.center, p1, p2, R) + val a3 = CircleTrajectory2D.of(c2.center, p2, end, L) CompositeTrajectory2D(a1, a2, a3) } @@ -211,8 +207,8 @@ public object DubinsPath { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = outerTangent(c1, c2, L) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.R) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.R) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, R) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) return CompositeTrajectory2D(a1, s, a3) } @@ -220,8 +216,8 @@ public object DubinsPath { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = outerTangent(c1, c2, R) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.L) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.L) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, L) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) return CompositeTrajectory2D(a1, s, a3) } @@ -231,8 +227,8 @@ public object DubinsPath { val s = innerTangent(c1, c2, R) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.R) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.L) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, R) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) return CompositeTrajectory2D(a1, s, a3) } @@ -242,8 +238,8 @@ public object DubinsPath { val s = innerTangent(c1, c2, L) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, Trajectory2D.Type.L) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, Trajectory2D.Type.R) + val a1 = CircleTrajectory2D.of(c1.center, start, s.start, L) + val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) return CompositeTrajectory2D(a1, s, a3) } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 7bf17fc26..d6974b105 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -17,10 +17,21 @@ import kotlin.math.atan2 public sealed interface Trajectory2D { public val length: Double - public enum class Type { - R, - S, - L + + public sealed interface Type + + public sealed interface Direction: Type + + public object R : Direction { + override fun toString(): String = "R" + } + + public object S : Type { + override fun toString(): String = "L" + } + + public object L : Direction { + override fun toString(): String = "L" } } @@ -56,7 +67,7 @@ public data class CircleTrajectory2D( * Arc length in radians */ val arcLength: Angle - get() = if (direction == Trajectory2D.Type.L) { + get() = if (direction == Trajectory2D.L) { start.bearing - end.bearing } else { end.bearing - start.bearing @@ -67,16 +78,16 @@ public data class CircleTrajectory2D( circle.radius * arcLength.radians } - public val direction: Trajectory2D.Type by lazy { + public val direction: Trajectory2D.Direction by lazy { if (start.y < circle.center.y) { - if (start.bearing > Angle.pi) Trajectory2D.Type.R else Trajectory2D.Type.L + if (start.bearing > Angle.pi) Trajectory2D.R else Trajectory2D.L } else if (start.y > circle.center.y) { - if (start.bearing < Angle.pi) Trajectory2D.Type.R else Trajectory2D.Type.L + if (start.bearing < Angle.pi) Trajectory2D.R else Trajectory2D.L } else { if (start.bearing == Angle.zero) { - if (start.x < circle.center.x) Trajectory2D.Type.R else Trajectory2D.Type.L + if (start.x < circle.center.x) Trajectory2D.R else Trajectory2D.L } else { - if (start.x > circle.center.x) Trajectory2D.Type.R else Trajectory2D.Type.L + if (start.x > circle.center.x) Trajectory2D.R else Trajectory2D.L } } } @@ -86,18 +97,17 @@ public data class CircleTrajectory2D( center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, - direction: Trajectory2D.Type, + direction: Trajectory2D.Direction, ): CircleTrajectory2D { fun calculatePose( vector: DoubleVector2D, theta: Angle, - direction: Trajectory2D.Type, + direction: Trajectory2D.Direction, ): DubinsPose2D = DubinsPose2D( vector, when (direction) { - Trajectory2D.Type.L -> (theta - Angle.piDiv2).normalized() - Trajectory2D.Type.R -> (theta + Angle.piDiv2).normalized() - else -> error("S trajectory type is not allowed in circle constructor") + Trajectory2D.L -> (theta - Angle.piDiv2).normalized() + Trajectory2D.R -> (theta + Angle.piDiv2).normalized() } ) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt index 446e0a4d3..150b370d0 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt @@ -38,7 +38,7 @@ class ObstacleTest { obstacles ) val length = outputTangents.minOf { it.length } - assertEquals(length, 27.2113183, 1e-6) + assertEquals(27.2113183, length, 1e-6) } @Test @@ -77,7 +77,7 @@ class ObstacleTest { obstacles ) val length = paths.minOf { it.length } - assertEquals(length, 28.9678224, 1e-6) + assertEquals(28.9678224, length, 1e-6) } @Test 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 index f149004bb..b3825b93b 100644 --- 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 @@ -23,7 +23,7 @@ class ArcTests { circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), - Trajectory2D.Type.R + Trajectory2D.R ) assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.start.bearing.degrees) From fd35d7c6143a5f544788bfda005cc399dc3cb245 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 15:28:02 +0300 Subject: [PATCH 65/72] [WIP] refactoring directions --- .../kscience/kmath/trajectory/Obstacle.kt | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index d5d04e1a4..b4ae04342 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -350,13 +350,13 @@ private fun arcLength( circle: Circle2D, point1: DoubleVector2D, point2: DoubleVector2D, - route: Trajectory2D.Type, + direction: Trajectory2D.Direction, ): Double { val phi1 = atan2(point1.y - circle.center.y, point1.x - circle.center.x) val phi2 = atan2(point2.y - circle.center.y, point2.x - circle.center.x) var angle = 0.0 - when (route) { - Trajectory2D.Type.L -> { + when (direction) { + Trajectory2D.L -> { angle = if (phi2 >= phi1) { phi2 - phi1 } else { @@ -364,17 +364,13 @@ private fun arcLength( } } - Trajectory2D.Type.R -> { + Trajectory2D.R -> { angle = if (phi2 >= phi1) { 2 * PI - (phi2 - phi1) } else { -(phi2 - phi1) } } - - Trajectory2D.Type.S -> { - error("L or R route is expected") - } } return circle.radius * angle } @@ -396,13 +392,13 @@ private fun constructTangentCircles( val p1 = center1 - point return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI / 2, -3 * PI / 2)) { mapOf( - Trajectory2D.Type.L to Circle2D(center1, r), - Trajectory2D.Type.R to Circle2D(center2, r) + Trajectory2D.L to Circle2D(center1, r), + Trajectory2D.R to Circle2D(center2, r) ) } else { mapOf( - Trajectory2D.Type.L to Circle2D(center2, r), - Trajectory2D.Type.R to Circle2D(center1, r) + Trajectory2D.L to Circle2D(center2, r), + Trajectory2D.R to Circle2D(center1, r) ) } } @@ -483,8 +479,8 @@ internal fun findAllPaths( finalRadius ) val trajectories = mutableListOf() - for (i in listOf(Trajectory2D.Type.L, Trajectory2D.Type.R)) { - for (j in listOf(Trajectory2D.Type.L, Trajectory2D.Type.R)) { + for (i in listOf(Trajectory2D.L, Trajectory2D.R)) { + for (j in listOf(Trajectory2D.L, Trajectory2D.R)) { val finalCircle = finalCircles[j]!! val finalObstacle = Obstacle(listOf(finalCircle)) var currentPaths: List = listOf( @@ -495,7 +491,7 @@ internal fun findAllPaths( Obstacle(listOf(initialCircles[i]!!)), Obstacle(listOf(initialCircles[i]!!)), LineSegment2D(startingPoint, startingPoint), - listOf(i, Trajectory2D.Type.S, i) + listOf(i, Trajectory2D.S, i) ) ) ) @@ -503,13 +499,13 @@ internal fun findAllPaths( val newPaths = mutableListOf() for (tangentPath: TangentPath in currentPaths) { val currentCircle = tangentPath.last().endCircle - val currentDirection = tangentPath.last().trajectoryType.last() + val currentDirection: Trajectory2D.Direction = tangentPath.last().trajectoryType.last() val currentObstacle = tangentPath.last().endObstacle var nextObstacle: Obstacle? = null if (currentObstacle != finalObstacle) { val tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.Type( currentDirection, - Trajectory2D.Type.S, + Trajectory2D.S, j )] for (obstacle in sortedObstacles(currentObstacle, obstacles)) { @@ -538,7 +534,7 @@ internal fun findAllPaths( tangent.startCircle, DubinsPath.Type( currentDirection, - Trajectory2D.Type.S, + Trajectory2D.S, currentDirection ), ).lineSegment.begin, @@ -555,7 +551,7 @@ internal fun findAllPaths( currentCircle, DubinsPath.Type( currentDirection, - Trajectory2D.Type.S, + Trajectory2D.S, currentDirection ), tangent.startCircle, @@ -569,7 +565,7 @@ internal fun findAllPaths( currentCircle, DubinsPath.Type( currentDirection, - Trajectory2D.Type.S, + Trajectory2D.S, currentDirection ), tangent.startCircle, @@ -599,7 +595,7 @@ internal fun findAllPaths( LineSegment2D(finalPoint, finalPoint), listOf( lastDirection, - Trajectory2D.Type.S, + Trajectory2D.S, j ) ) From 1e46ffbd98809c43b14c5b8f4df65f9315d040c7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 16:50:30 +0300 Subject: [PATCH 66/72] refactoring directions --- .../kscience/kmath/trajectory/Obstacle.kt | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index b4ae04342..c4ff34295 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -21,7 +21,8 @@ internal data class Tangent( val startObstacle: Obstacle, val endObstacle: Obstacle, val lineSegment: LineSegment2D, - val trajectoryType: List, + val startDirection: Trajectory2D.Direction, + val endDirection: Trajectory2D.Direction = startDirection ) private class TangentPath(val tangents: List) { @@ -131,7 +132,8 @@ private fun dubinsTangentsToCircles( firstCircle.center + w * r1, secondCircle.center + w * r2 ), - trajectoryType = route.toList() + startDirection = route.first, + endDirection = route.third ) ) } else { @@ -194,7 +196,8 @@ public class Obstacle( center + w * r1, other.center + w * r2 ), - routeType.toList() + startDirection = routeType.first, + endDirection = routeType.third ) ) } else { @@ -256,7 +259,8 @@ private fun Obstacle.nextTangent(circle: Circle2D, routeType: DubinsPath.Type): tangents[i - 1].lineSegment.end, tangents[i - 1].lineSegment.begin ), - routeType.toList() + startDirection = routeType.first, + endDirection = routeType.third ) } else { return Tangent( @@ -268,7 +272,8 @@ private fun Obstacle.nextTangent(circle: Circle2D, routeType: DubinsPath.Type): tangents.last().lineSegment.end, tangents.last().lineSegment.begin ), - routeType.toList() + startDirection = routeType.first, + endDirection = routeType.third ) } } @@ -450,7 +455,7 @@ private fun TangentPath.toTrajectory(): CompositeTrajectory2D = CompositeTraject right.startCircle.center, left.lineSegment.end, right.lineSegment.begin, - right.trajectoryType.first() + right.startDirection ) ) } @@ -491,7 +496,7 @@ internal fun findAllPaths( Obstacle(listOf(initialCircles[i]!!)), Obstacle(listOf(initialCircles[i]!!)), LineSegment2D(startingPoint, startingPoint), - listOf(i, Trajectory2D.S, i) + i ) ) ) @@ -499,7 +504,7 @@ internal fun findAllPaths( val newPaths = mutableListOf() for (tangentPath: TangentPath in currentPaths) { val currentCircle = tangentPath.last().endCircle - val currentDirection: Trajectory2D.Direction = tangentPath.last().trajectoryType.last() + val currentDirection: Trajectory2D.Direction = tangentPath.last().endDirection val currentObstacle = tangentPath.last().endObstacle var nextObstacle: Obstacle? = null if (currentObstacle != finalObstacle) { @@ -583,7 +588,7 @@ internal fun findAllPaths( } trajectories += currentPaths.map { tangentPath -> - val lastDirection: Trajectory2D.Type = tangentPath.last().trajectoryType[2] + val lastDirection: Trajectory2D.Direction = tangentPath.last().endDirection val end = finalCircles[j]!! TangentPath( tangentPath.tangents + @@ -593,11 +598,8 @@ internal fun findAllPaths( Obstacle(end), Obstacle(end), LineSegment2D(finalPoint, finalPoint), - listOf( - lastDirection, - Trajectory2D.S, - j - ) + startDirection = lastDirection, + endDirection = j ) ) }.map { it.toTrajectory() } From f5201b6be0c2cf784e2a192193d2f7130caac857 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 17:42:40 +0300 Subject: [PATCH 67/72] refactoring directions --- .../kotlin/space/kscience/kmath/trajectory/Obstacle.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index c4ff34295..553ca0388 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -69,7 +69,7 @@ internal fun Circle2D.tangentsToCircle( } else { angle1 - r2.sign * atan2(r.absoluteValue, l) } - val w = Euclidean2DSpace.vector(-cos(angle2), sin(angle2)) + val w = vector(-cos(angle2), sin(angle2)) put( route, LineSegment( @@ -412,7 +412,7 @@ private fun sortedObstacles( currentObstacle: Obstacle, obstacles: List, ): List { - return obstacles.sortedBy { norm(it.center - currentObstacle.center) }//.reversed() + return obstacles.sortedBy { norm(it.center - currentObstacle.center) } } private fun tangentsAlongTheObstacle( @@ -580,7 +580,6 @@ internal fun findAllPaths( newPaths.add(TangentPath(tangentPath.tangents + tangentsAlong + tangent)) } } else { - // minor changes from Python code newPaths.add(tangentPath) } } From 639a255aaf96c3b41a458774036b3f48efd86765 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 18:50:17 +0300 Subject: [PATCH 68/72] refactoring directions --- .../kscience/kmath/trajectory/DubinsPose2D.kt | 18 +++++++++++++-- .../kscience/kmath/trajectory/Obstacle.kt | 22 +++++++++---------- .../kscience/kmath/trajectory/ObstacleTest.kt | 12 ++++------ 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt index 8362d0cb5..078e158ea 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt @@ -3,6 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:UseSerializers(Euclidean2DSpace.VectorSerializer::class) + package space.kscience.kmath.trajectory import kotlinx.serialization.KSerializer @@ -22,6 +23,19 @@ import kotlin.math.atan2 public interface DubinsPose2D : DoubleVector2D { public val coordinates: DoubleVector2D public val bearing: Angle + + public companion object { + public fun bearingToVector(bearing: Angle): Vector2D = + Euclidean2DSpace.vector(cos(bearing), sin(bearing)) + + public fun vectorToBearing(vector2D: DoubleVector2D): Angle { + require(vector2D.x != 0.0 || vector2D.y != 0.0) { "Can't get bearing of zero vector" } + return atan2(vector2D.y, vector2D.x).radians + } + + public fun of(point: DoubleVector2D, direction: DoubleVector2D): DubinsPose2D = + DubinsPose2D(point, vectorToBearing(direction)) + } } @Serializable @@ -37,12 +51,12 @@ public class PhaseVector2D( private class DubinsPose2DImpl( override val coordinates: DoubleVector2D, override val bearing: Angle, -) : DubinsPose2D, DoubleVector2D by coordinates{ +) : DubinsPose2D, DoubleVector2D by coordinates { override fun toString(): String = "DubinsPose2D(x=$x, y=$y, bearing=$bearing)" } -public object DubinsPose2DSerializer: KSerializer{ +public object DubinsPose2DSerializer : KSerializer { private val proxySerializer = DubinsPose2DImpl.serializer() override val descriptor: SerialDescriptor diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index 553ca0388..a00fe24d4 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -22,7 +22,7 @@ internal data class Tangent( val endObstacle: Obstacle, val lineSegment: LineSegment2D, val startDirection: Trajectory2D.Direction, - val endDirection: Trajectory2D.Direction = startDirection + val endDirection: Trajectory2D.Direction = startDirection, ) private class TangentPath(val tangents: List) { @@ -465,22 +465,22 @@ private fun TangentPath.toTrajectory(): CompositeTrajectory2D = CompositeTraject ) internal fun findAllPaths( - startingPoint: DoubleVector2D, - startingDirection: DoubleVector2D, + start: DubinsPose2D, startingRadius: Double, - finalPoint: DoubleVector2D, - finalDirection: DoubleVector2D, + finish: DubinsPose2D, finalRadius: Double, obstacles: List, ): List { + fun DubinsPose2D.direction() = vector(cos(bearing),sin(bearing)) + val initialCircles = constructTangentCircles( - startingPoint, - startingDirection, + start, + start.direction(), startingRadius ) val finalCircles = constructTangentCircles( - finalPoint, - finalDirection, + finish, + finish.direction(), finalRadius ) val trajectories = mutableListOf() @@ -495,7 +495,7 @@ internal fun findAllPaths( initialCircles[i]!!, Obstacle(listOf(initialCircles[i]!!)), Obstacle(listOf(initialCircles[i]!!)), - LineSegment2D(startingPoint, startingPoint), + LineSegment2D(start, start), i ) ) @@ -596,7 +596,7 @@ internal fun findAllPaths( end, Obstacle(end), Obstacle(end), - LineSegment2D(finalPoint, finalPoint), + LineSegment2D(finish, finish), startDirection = lastDirection, endDirection = j ) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt index 150b370d0..1a8c3a474 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt @@ -29,11 +29,9 @@ class ObstacleTest { ) val outputTangents = findAllPaths( - startPoint, - startDirection, + DubinsPose2D.of(startPoint, startDirection), startRadius, - finalPoint, - finalDirection, + DubinsPose2D.of(finalPoint, finalDirection), finalRadius, obstacles ) @@ -68,11 +66,9 @@ class ObstacleTest { ) ) val paths = findAllPaths( - startPoint, - startDirection, + DubinsPose2D.of(startPoint, startDirection), startRadius, - finalPoint, - finalDirection, + DubinsPose2D.of(finalPoint, finalDirection), finalRadius, obstacles ) From 025cb5806030665550f0767bc7de8ecec7ad3c7a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 19:02:24 +0300 Subject: [PATCH 69/72] refactoring directions --- .../kscience/kmath/trajectory/Obstacle.kt | 112 ++++++++---------- 1 file changed, 49 insertions(+), 63 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index a00fe24d4..f2768bbca 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -229,6 +229,48 @@ public class Obstacle( } } + internal fun nextTangent(circle: Circle2D, direction: Trajectory2D.Direction): Tangent { + if (direction == boundaryRoute.first) { + for (i in circles.indices) { + if (circles[i] == circle) { + return tangents[i] + } + } + } else { + for (i in circles.indices) { + if (circles[i] == circle) { + if (i > 0) { + return Tangent( + circles[i], + circles[i - 1], + this, + this, + LineSegment2D( + tangents[i - 1].lineSegment.end, + tangents[i - 1].lineSegment.begin + ), + direction + ) + } else { + return Tangent( + circles[0], + circles.last(), + this, + this, + LineSegment2D( + tangents.last().lineSegment.end, + tangents.last().lineSegment.begin + ), + direction + ) + } + } + } + } + + error("next tangent not found") + } + override fun equals(other: Any?): Boolean { if (other == null || other !is Obstacle) return false return circles == other.circles @@ -239,50 +281,6 @@ public class Obstacle( } } -private fun Obstacle.nextTangent(circle: Circle2D, routeType: DubinsPath.Type): Tangent { - if (routeType == boundaryRoute) { - for (i in circles.indices) { - if (circles[i] == circle) { - return tangents[i] - } - } - } else { - for (i in circles.indices) { - if (circles[i] == circle) { - if (i > 0) { - return Tangent( - circles[i], - circles[i - 1], - this, - this, - LineSegment2D( - tangents[i - 1].lineSegment.end, - tangents[i - 1].lineSegment.begin - ), - startDirection = routeType.first, - endDirection = routeType.third - ) - } else { - return Tangent( - circles[0], - circles.last(), - this, - this, - LineSegment2D( - tangents.last().lineSegment.end, - tangents.last().lineSegment.begin - ), - startDirection = routeType.first, - endDirection = routeType.third - ) - } - } - } - } - - error("next tangent not found") -} - public fun Obstacle(vararg circles: Circle2D): Obstacle = Obstacle(listOf(*circles)) private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { @@ -417,15 +415,15 @@ private fun sortedObstacles( private fun tangentsAlongTheObstacle( initialCircle: Circle2D, - initialRoute: DubinsPath.Type, + direction: Trajectory2D.Direction, finalCircle: Circle2D, obstacle: Obstacle, ): List { val dubinsTangents = mutableListOf() - var tangent = obstacle.nextTangent(initialCircle, initialRoute) + var tangent = obstacle.nextTangent(initialCircle, direction) dubinsTangents.add(tangent) while (tangent.endCircle != finalCircle) { - tangent = obstacle.nextTangent(tangent.endCircle, initialRoute) + tangent = obstacle.nextTangent(tangent.endCircle, direction) dubinsTangents.add(tangent) } return dubinsTangents @@ -471,7 +469,7 @@ internal fun findAllPaths( finalRadius: Double, obstacles: List, ): List { - fun DubinsPose2D.direction() = vector(cos(bearing),sin(bearing)) + fun DubinsPose2D.direction() = vector(cos(bearing), sin(bearing)) val initialCircles = constructTangentCircles( start, @@ -537,11 +535,7 @@ internal fun findAllPaths( tangentPath.last().lineSegment.end, tangent.startObstacle.nextTangent( tangent.startCircle, - DubinsPath.Type( - currentDirection, - Trajectory2D.S, - currentDirection - ), + currentDirection ).lineSegment.begin, currentDirection ) @@ -554,11 +548,7 @@ internal fun findAllPaths( tangentsAlong = if (lengthCalculated > lengthMaxPossible) { tangentsAlongTheObstacle( currentCircle, - DubinsPath.Type( - currentDirection, - Trajectory2D.S, - currentDirection - ), + currentDirection, tangent.startCircle, currentObstacle ) @@ -568,11 +558,7 @@ internal fun findAllPaths( } else { tangentsAlong = tangentsAlongTheObstacle( currentCircle, - DubinsPath.Type( - currentDirection, - Trajectory2D.S, - currentDirection - ), + currentDirection, tangent.startCircle, currentObstacle ) From a0e2ef1afc08765240f0e00ac39205a25bdc92e8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 19:33:43 +0300 Subject: [PATCH 70/72] refactor lines and segments --- .../space/kscience/kmath/geometry/Line.kt | 27 ++++++++++++++++--- .../kscience/kmath/geometry/projections.kt | 2 +- .../kscience/kmath/trajectory/Obstacle.kt | 14 +++++----- .../kscience/kmath/trajectory/Trajectory2D.kt | 2 +- 4 files changed, 32 insertions(+), 13 deletions(-) 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 e593150f1..a7f6ae35d 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 @@ -5,15 +5,23 @@ package space.kscience.kmath.geometry +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import space.kscience.kmath.operations.DoubleField.pow /** - * A line formed by [base] vector of start and a [direction] vector. Direction vector is not necessarily normalized, + * A line formed by [start] vector of start and a [direction] vector. Direction vector is not necessarily normalized, * but its length does not affect line properties */ +public interface Line { + public val start: V + public val direction: V +} + @Serializable -public data class Line(val base: V, val direction: V) +@SerialName("Line") +private data class LineImpl(override val start: V, override val direction: V): Line + +public fun Line(base: V, direction: V): Line = LineImpl(base, direction) public typealias Line2D = Line public typealias Line3D = Line @@ -21,8 +29,19 @@ public typealias Line3D = Line /** * A directed line segment between [begin] and [end] */ +public interface LineSegment { + public val begin: V + public val end: V +} + +/** + * Basic implementation for [LineSegment] + */ @Serializable -public data class LineSegment(val begin: V, val end: V) +@SerialName("LineSegment") +private data class LineSegmentImpl(override val begin: V, override val end: V) : LineSegment + +public fun LineSegment(begin: V, end: V): LineSegment = LineSegmentImpl(begin, end) public fun LineSegment.line(algebra: GeometrySpace): Line = with(algebra) { Line(begin, end - begin) 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 index 6950abbdc..c5c3487a1 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 @@ -13,7 +13,7 @@ package space.kscience.kmath.geometry * @param line line to which vector should be projected */ public fun GeometrySpace.projectToLine(vector: V, line: Line): V = with(line) { - base + (direction dot (vector - base)) / (direction dot direction) * direction + start + (direction dot (vector - start)) / (direction dot direction) * direction } /** diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index f2768bbca..3819afb54 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -23,7 +23,7 @@ internal data class Tangent( val lineSegment: LineSegment2D, val startDirection: Trajectory2D.Direction, val endDirection: Trajectory2D.Direction = startDirection, -) +): LineSegment2D by lineSegment private class TangentPath(val tangents: List) { fun last() = tangents.last() @@ -128,7 +128,7 @@ private fun dubinsTangentsToCircles( endCircle = secondCircle, startObstacle = firstObstacle, endObstacle = secondObstacle, - lineSegment = LineSegment2D( + lineSegment = LineSegment( firstCircle.center + w * r1, secondCircle.center + w * r2 ), @@ -192,7 +192,7 @@ public class Obstacle( other, this@Obstacle, this@Obstacle, - LineSegment2D( + LineSegment( center + w * r1, other.center + w * r2 ), @@ -245,7 +245,7 @@ public class Obstacle( circles[i - 1], this, this, - LineSegment2D( + LineSegment( tangents[i - 1].lineSegment.end, tangents[i - 1].lineSegment.begin ), @@ -257,7 +257,7 @@ public class Obstacle( circles.last(), this, this, - LineSegment2D( + LineSegment( tangents.last().lineSegment.end, tangents.last().lineSegment.begin ), @@ -493,7 +493,7 @@ internal fun findAllPaths( initialCircles[i]!!, Obstacle(listOf(initialCircles[i]!!)), Obstacle(listOf(initialCircles[i]!!)), - LineSegment2D(start, start), + LineSegment(start, start), i ) ) @@ -582,7 +582,7 @@ internal fun findAllPaths( end, Obstacle(end), Obstacle(end), - LineSegment2D(finish, finish), + LineSegment(finish, finish), startDirection = lastDirection, endDirection = j ) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index d6974b105..8df0de237 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -50,7 +50,7 @@ public data class StraightTrajectory2D( public val bearing: Angle get() = (atan2(end.x - start.x, end.y - start.y).radians).normalized() } -public fun StraightTrajectory2D.toSegment(): LineSegment> = LineSegment2D(start, end) +public fun StraightTrajectory2D.toSegment(): LineSegment> = LineSegment(start, end) /** * An arc segment From 00ce7d5a48e4736ec6d80a480327a2c550787425 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 5 Apr 2023 13:30:13 +0300 Subject: [PATCH 71/72] Obstacle avoidance finished --- .../space/kscience/kmath/geometry/Polygon.kt | 14 +++++++++++++ .../kmath/geometry/ProjectionOntoLineTest.kt | 4 ++-- .../kscience/kmath/trajectory/DubinsPath.kt | 10 +++++----- .../kscience/kmath/trajectory/Obstacle.kt | 20 +++++++++++++++---- .../kscience/kmath/trajectory/Trajectory2D.kt | 12 +++++------ .../kscience/kmath/trajectory/DubinsTests.kt | 4 ++-- .../space/kscience/kmath/trajectory/math.kt | 4 ++-- 7 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Polygon.kt diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Polygon.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Polygon.kt new file mode 100644 index 000000000..20f4a031e --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Polygon.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2023 KMath 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 closed polygon in 2D space + */ +public interface Polygon { + public val points: List> +} \ No newline at end of file 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 cdb8ea870..7c6c105cf 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 @@ -63,7 +63,7 @@ internal class ProjectionOntoLineTest { @Test fun projectionOntoLine3d() = with(Euclidean3DSpace) { - val line = Line3D( + val line = Line( base = vector(1.0, 3.5, 0.07), direction = vector(2.0, -0.0037, 11.1111) ) @@ -77,7 +77,7 @@ internal class ProjectionOntoLineTest { val result = projectToLine(v, line) // assert that result is on the line - assertTrue(isCollinear(result - line.base, line.direction)) + assertTrue(isCollinear(result - line.start, line.direction)) // assert that PV vector is orthogonal to direction vector assertTrue(isOrthogonal(v - result, line.direction)) } 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 index 87ea52a69..a1563b29c 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -36,7 +36,7 @@ private fun outerTangent(from: Circle2D, to: Circle2D, direction: Direction): St } return StraightTrajectory2D( p1, - vector(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) + vector(p1.x + (centers.end.x - centers.begin.x), p1.y + (centers.end.y - centers.begin.y)) ) } @@ -207,7 +207,7 @@ public object DubinsPath { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = outerTangent(c1, c2, L) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, R) + val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, R) val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) return CompositeTrajectory2D(a1, s, a3) } @@ -216,7 +216,7 @@ public object DubinsPath { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = outerTangent(c1, c2, R) - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, L) + val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, L) val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) return CompositeTrajectory2D(a1, s, a3) } @@ -227,7 +227,7 @@ public object DubinsPath { val s = innerTangent(c1, c2, R) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, R) + val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, R) val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) return CompositeTrajectory2D(a1, s, a3) } @@ -238,7 +238,7 @@ public object DubinsPath { val s = innerTangent(c1, c2, L) if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - val a1 = CircleTrajectory2D.of(c1.center, start, s.start, L) + val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, L) val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) return CompositeTrajectory2D(a1, s, a3) } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt index 3819afb54..32061efea 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt @@ -23,7 +23,7 @@ internal data class Tangent( val lineSegment: LineSegment2D, val startDirection: Trajectory2D.Direction, val endDirection: Trajectory2D.Direction = startDirection, -): LineSegment2D by lineSegment +) : LineSegment2D by lineSegment private class TangentPath(val tangents: List) { fun last() = tangents.last() @@ -143,7 +143,7 @@ private fun dubinsTangentsToCircles( } } -public class Obstacle( +internal class Obstacle( public val circles: List, ) { internal val tangents: List = boundaryTangents().first @@ -281,7 +281,7 @@ public class Obstacle( } } -public fun Obstacle(vararg circles: Circle2D): Obstacle = Obstacle(listOf(*circles)) +internal fun Obstacle(vararg circles: Circle2D): Obstacle = Obstacle(listOf(*circles)) private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { @@ -594,7 +594,19 @@ internal fun findAllPaths( } - +public object Obstacles { + public fun allPathsAvoiding( + start: DubinsPose2D, + finish: DubinsPose2D, + trajectoryRadius: Double, + obstaclePolygons: List>, + ): List { + val obstacles: List = obstaclePolygons.map { polygon -> + Obstacle(polygon.points.map { point -> Circle2D(point, trajectoryRadius) }) + } + return findAllPaths(start, trajectoryRadius, finish, trajectoryRadius, obstacles) + } +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt index 8df0de237..59a8e613a 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt @@ -41,17 +41,15 @@ public sealed interface Trajectory2D { @Serializable @SerialName("straight") public data class StraightTrajectory2D( - public val start: DoubleVector2D, - public val end: DoubleVector2D, -) : Trajectory2D { + override val begin: DoubleVector2D, + override val end: DoubleVector2D, +) : Trajectory2D, LineSegment2D { - override val length: Double get() = start.distanceTo(end) + override val length: Double get() = begin.distanceTo(end) - public val bearing: Angle get() = (atan2(end.x - start.x, end.y - start.y).radians).normalized() + public val bearing: Angle get() = (atan2(end.x - begin.x, end.y - begin.y).radians).normalized() } -public fun StraightTrajectory2D.toSegment(): LineSegment> = LineSegment(start, end) - /** * An arc segment */ diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt index f5bfb884e..80f7173f1 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt @@ -20,7 +20,7 @@ class DubinsTests { val lineP1 = straight.shift(1, 10.0).inverse() val start = DubinsPose2D(straight.end, straight.bearing) - val end = DubinsPose2D(lineP1.start, lineP1.bearing) + val end = DubinsPose2D(lineP1.begin, lineP1.bearing) val radius = 2.0 val dubins = DubinsPath.all(start, end, radius) @@ -53,7 +53,7 @@ class DubinsTests { assertTrue(a.end.equalsFloat(b.start)) assertTrue(c.start.equalsFloat(b.end)) } else if (b is StraightTrajectory2D) { - assertTrue(a.end.equalsFloat(DubinsPose2D(b.start, b.bearing))) + assertTrue(a.end.equalsFloat(DubinsPose2D(b.begin, b.bearing))) assertTrue(c.start.equalsFloat(DubinsPose2D(b.end, b.bearing))) } } 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 index 24685f528..8b8ccf95e 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt @@ -14,14 +14,14 @@ import space.kscience.kmath.geometry.sin fun DubinsPose2D.equalsFloat(other: DubinsPose2D) = x.equalsFloat(other.x) && y.equalsFloat(other.y) && bearing.radians.equalsFloat(other.bearing.radians) -fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, start) +fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, begin) fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace) { val dX = width * sin(inverse().bearing) val dY = width * sin(bearing) return StraightTrajectory2D( - vector(start.x - dX * shift, start.y - dY * shift), + vector(begin.x - dX * shift, begin.y - dY * shift), vector(end.x - dX * shift, end.y - dY * shift) ) } From 7cc6a4be400bb7195dba6df50259a2c48cee849f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 5 Apr 2023 15:26:09 +0300 Subject: [PATCH 72/72] remove trajectory --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- gradle.properties | 2 +- kmath-trajectory/README.md | 34 - kmath-trajectory/build.gradle.kts | 21 - kmath-trajectory/docs/README-TEMPLATE.md | 13 - .../kscience/kmath/trajectory/DubinsPath.kt | 258 -------- .../kscience/kmath/trajectory/DubinsPose2D.kt | 75 --- .../kscience/kmath/trajectory/Obstacle.kt | 614 ------------------ .../kscience/kmath/trajectory/Trajectory2D.kt | 131 ---- .../kscience/kmath/trajectory/DubinsTests.kt | 61 -- .../kscience/kmath/trajectory/ObstacleTest.kt | 88 --- .../kscience/kmath/trajectory/TangentTest.kt | 64 -- .../space/kscience/kmath/trajectory/math.kt | 27 - .../kmath/trajectory/segments/ArcTests.kt | 32 - .../kmath/trajectory/segments/CircleTests.kt | 24 - .../kmath/trajectory/segments/LineTests.kt | 37 -- settings.gradle.kts | 1 - 18 files changed, 3 insertions(+), 1482 deletions(-) delete mode 100644 kmath-trajectory/README.md delete mode 100644 kmath-trajectory/build.gradle.kts delete mode 100644 kmath-trajectory/docs/README-TEMPLATE.md delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt delete mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index c5fa3f372..24b592430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ ### Deprecated ### Removed +- Trajectory moved to https://github.com/SciProgCentre/maps-kt - Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial ### Fixed diff --git a/build.gradle.kts b/build.gradle.kts index 9b1101a22..cd8dfb4a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-10" + version = "0.3.1-dev-11" } subprojects { diff --git a/gradle.properties b/gradle.properties index 262bcabfb..e33106c0c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ kotlin.native.ignoreDisabledTargets=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.14.5-kotlin-1.8.20-RC +toolsVersion=0.14.6-kotlin-1.8.20 org.gradle.parallel=true diff --git a/kmath-trajectory/README.md b/kmath-trajectory/README.md deleted file mode 100644 index ac2930b04..000000000 --- a/kmath-trajectory/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# 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 deleted file mode 100644 index 32b87bb06..000000000 --- a/kmath-trajectory/build.gradle.kts +++ /dev/null @@ -1,21 +0,0 @@ -plugins { - id("space.kscience.gradle.mpp") -} - -kscience{ - jvm() - js() - native() - - useContextReceivers() - useSerialization() - dependencies { - api(projects.kmath.kmathGeometry) - } -} - -readme { - description = "Path and trajectory optimization (to be moved to a separate project)" - maturity = space.kscience.gradle.Maturity.DEPRECATED - 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 deleted file mode 100644 index eb8e4a0c0..000000000 --- a/kmath-trajectory/docs/README-TEMPLATE.md +++ /dev/null @@ -1,13 +0,0 @@ -# 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 deleted file mode 100644 index a1563b29c..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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.* -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.trajectory.Trajectory2D.* -import kotlin.math.acos - -internal fun DubinsPose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first - -internal fun DubinsPose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second - -internal fun DubinsPose2D.getTangentCircles(radius: Double): Pair = with(Euclidean2DSpace) { - val dX = radius * cos(bearing) - val dY = radius * sin(bearing) - return Circle2D(vector(x - dX, y + dY), radius) to Circle2D(vector(x + dX, y - dY), radius) -} - -private fun outerTangent(from: Circle2D, to: Circle2D, direction: Direction): StraightTrajectory2D = - with(Euclidean2DSpace) { - val centers = StraightTrajectory2D(from.center, to.center) - val p1 = when (direction) { - L -> vector( - from.center.x - from.radius * cos(centers.bearing), - from.center.y + from.radius * sin(centers.bearing) - ) - - R -> vector( - from.center.x + from.radius * cos(centers.bearing), - from.center.y - from.radius * sin(centers.bearing) - ) - } - return StraightTrajectory2D( - p1, - vector(p1.x + (centers.end.x - centers.begin.x), p1.y + (centers.end.y - centers.begin.y)) - ) - } - - -private fun innerTangent( - from: Circle2D, - to: Circle2D, - direction: Direction, -): StraightTrajectory2D? = - with(Euclidean2DSpace) { - val centers = StraightTrajectory2D(from.center, to.center) - if (centers.length < from.radius * 2) return null - val angle = when (direction) { - L -> centers.bearing + acos(from.radius * 2 / centers.length).radians - R -> centers.bearing - acos(from.radius * 2 / centers.length).radians - }.normalized() - - val dX = from.radius * sin(angle) - val dY = from.radius * cos(angle) - val p1 = vector(from.center.x + dX, from.center.y + dY) - val p2 = vector(to.center.x - dX, to.center.y - dY) - return StraightTrajectory2D(p1, p2) - } - - -@Suppress("DuplicatedCode") -public object DubinsPath { - - public data class Type( - public val first: Direction, - public val second: Trajectory2D.Type, - public val third: Direction, - ) { - public fun toList(): List = listOf(first, second, third) - - override fun toString(): String = "${first}${second}${third}" - - public companion object { - public val RLR: Type = Type(R, L, R) - public val LRL: Type = Type(L, R, L) - public val RSR: Type = Type(R, S, R) - public val LSL: Type = Type(L, S, L) - public val RSL: Type = Type(R, S, L) - public val LSR: Type = Type(L, S, R) - } - } - - /** - * Return Dubins trajectory type or null if trajectory is not a Dubins path - */ - public fun trajectoryTypeOf(trajectory2D: CompositeTrajectory2D): Type? { - if (trajectory2D.segments.size != 3) return null - val a = trajectory2D.segments.first() as? CircleTrajectory2D ?: return null - val b = trajectory2D.segments[1] - val c = trajectory2D.segments.last() as? CircleTrajectory2D ?: return null - return Type( - a.direction, - if (b is CircleTrajectory2D) b.direction else S, - c.direction - ) - } - - public fun all( - start: DubinsPose2D, - end: DubinsPose2D, - 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: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D = - all(start, end, turningRadius).minBy { it.length } - - public fun rlr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? = - with(Euclidean2DSpace) { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val centers = StraightTrajectory2D(c1.center, c2.center) - if (centers.length > turningRadius * 4) return null - - val firstVariant = run { - var theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() - 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 = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, R) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, L) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, R) - CompositeTrajectory2D(a1, a2, a3) - } - - val secondVariant = run { - var theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() - 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 = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, R) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, L) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, R) - CompositeTrajectory2D(a1, a2, a3) - } - - return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant - } - - public fun lrl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? = - with(Euclidean2DSpace) { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val centers = StraightTrajectory2D(c1.center, c2.center) - if (centers.length > turningRadius * 4) return null - - val firstVariant = run { - var theta = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() - 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 = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, L) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, R) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, L) - CompositeTrajectory2D(a1, a2, a3) - } - - val secondVariant = run { - var theta = (centers.bearing - acos(centers.length / (turningRadius * 4)).radians).normalized() - 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 = (centers.bearing + acos(centers.length / (turningRadius * 4)).radians).normalized() - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = vector(e.center.x + dX, e.center.y + dY) - val a1 = CircleTrajectory2D.of(c1.center, start, p1, L) - val a2 = CircleTrajectory2D.of(e.center, p1, p2, R) - val a3 = CircleTrajectory2D.of(c2.center, p2, end, L) - CompositeTrajectory2D(a1, a2, a3) - } - - return if (firstVariant.length < secondVariant.length) firstVariant else secondVariant - } - - public fun rsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val s = outerTangent(c1, c2, L) - val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, R) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) - return CompositeTrajectory2D(a1, s, a3) - } - - public fun lsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val s = outerTangent(c1, c2, R) - val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, L) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) - return CompositeTrajectory2D(a1, s, a3) - } - - public fun rsl(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val s = innerTangent(c1, c2, R) - if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - - val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, R) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, L) - return CompositeTrajectory2D(a1, s, a3) - } - - public fun lsr(start: DubinsPose2D, end: DubinsPose2D, turningRadius: Double): CompositeTrajectory2D? { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val s = innerTangent(c1, c2, L) - if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null - - val a1 = CircleTrajectory2D.of(c1.center, start, s.begin, L) - val a3 = CircleTrajectory2D.of(c2.center, s.end, end, R) - return CompositeTrajectory2D(a1, s, a3) - } -} - -public typealias PathTypes = List - -public fun interface MaxCurvature { - public fun compute(startPoint: PhaseVector2D): Double -} - -public fun DubinsPath.shortest( - start: PhaseVector2D, - end: PhaseVector2D, - maxCurvature: MaxCurvature, -): CompositeTrajectory2D = shortest(start, end, maxCurvature.compute(start)) - diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt deleted file mode 100644 index 078e158ea..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPose2D.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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:UseSerializers(Euclidean2DSpace.VectorSerializer::class) - -package space.kscience.kmath.trajectory - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.UseSerializers -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import space.kscience.kmath.geometry.* -import kotlin.math.atan2 - -/** - * Combination of [Vector] and its view angle (clockwise from positive y-axis direction) - */ -@Serializable(DubinsPose2DSerializer::class) -public interface DubinsPose2D : DoubleVector2D { - public val coordinates: DoubleVector2D - public val bearing: Angle - - public companion object { - public fun bearingToVector(bearing: Angle): Vector2D = - Euclidean2DSpace.vector(cos(bearing), sin(bearing)) - - public fun vectorToBearing(vector2D: DoubleVector2D): Angle { - require(vector2D.x != 0.0 || vector2D.y != 0.0) { "Can't get bearing of zero vector" } - return atan2(vector2D.y, vector2D.x).radians - } - - public fun of(point: DoubleVector2D, direction: DoubleVector2D): DubinsPose2D = - DubinsPose2D(point, vectorToBearing(direction)) - } -} - -@Serializable -public class PhaseVector2D( - override val coordinates: DoubleVector2D, - public val velocity: DoubleVector2D, -) : DubinsPose2D, DoubleVector2D by coordinates { - override val bearing: Angle get() = atan2(velocity.x, velocity.y).radians -} - -@Serializable -@SerialName("DubinsPose2D") -private class DubinsPose2DImpl( - override val coordinates: DoubleVector2D, - override val bearing: Angle, -) : DubinsPose2D, DoubleVector2D by coordinates { - - override fun toString(): String = "DubinsPose2D(x=$x, y=$y, bearing=$bearing)" -} - -public object DubinsPose2DSerializer : KSerializer { - private val proxySerializer = DubinsPose2DImpl.serializer() - - override val descriptor: SerialDescriptor - get() = proxySerializer.descriptor - - override fun deserialize(decoder: Decoder): DubinsPose2D { - return decoder.decodeSerializableValue(proxySerializer) - } - - override fun serialize(encoder: Encoder, value: DubinsPose2D) { - val pose = value as? DubinsPose2DImpl ?: DubinsPose2DImpl(value.coordinates, value.bearing) - encoder.encodeSerializableValue(proxySerializer, pose) - } -} - -public fun DubinsPose2D(coordinate: DoubleVector2D, theta: Angle): DubinsPose2D = DubinsPose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt deleted file mode 100644 index 32061efea..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Obstacle.kt +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.* -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Euclidean2DSpace.minus -import space.kscience.kmath.geometry.Euclidean2DSpace.norm -import space.kscience.kmath.geometry.Euclidean2DSpace.plus -import space.kscience.kmath.geometry.Euclidean2DSpace.times -import space.kscience.kmath.geometry.Euclidean2DSpace.vector -import space.kscience.kmath.operations.DoubleField.pow -import kotlin.math.* - -internal data class Tangent( - val startCircle: Circle2D, - val endCircle: Circle2D, - val startObstacle: Obstacle, - val endObstacle: Obstacle, - val lineSegment: LineSegment2D, - val startDirection: Trajectory2D.Direction, - val endDirection: Trajectory2D.Direction = startDirection, -) : LineSegment2D by lineSegment - -private class TangentPath(val tangents: List) { - fun last() = tangents.last() -} - -private fun TangentPath(vararg tangents: Tangent) = TangentPath(listOf(*tangents)) - -/** - * Create inner and outer tangents between two circles. - * This method returns a map of segments using [DubinsPath] connection type notation. - */ -internal fun Circle2D.tangentsToCircle( - other: Circle2D, -): Map = with(Euclidean2DSpace) { - //return empty map for concentric circles - if (center.equalsVector(other.center)) return emptyMap() - - // A line connecting centers - val line = LineSegment(center, other.center) - // Distance between centers - val distance = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(radius, other.radius), - DubinsPath.Type.RSL to Pair(radius, -other.radius), - DubinsPath.Type.LSR to Pair(-radius, other.radius), - DubinsPath.Type.LSL to Pair(-radius, -other.radius) - ) - return buildMap { - for ((route, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - val r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (distance * distance >= r * r) { - val l = sqrt(distance * distance - r * r) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - route, - LineSegment( - center + w * r1, - other.center + w * r2 - ) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } -} - -private fun dubinsTangentsToCircles( - firstCircle: Circle2D, - secondCircle: Circle2D, - firstObstacle: Obstacle, - secondObstacle: Obstacle, -): Map = with(Euclidean2DSpace) { - val line = LineSegment(firstCircle.center, secondCircle.center) - val distance = line.begin.distanceTo(line.end) - val angle1 = atan2( - secondCircle.center.x - firstCircle.center.x, - secondCircle.center.y - firstCircle.center.y - ) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(firstCircle.radius, secondCircle.radius), - DubinsPath.Type.RSL to Pair(firstCircle.radius, -secondCircle.radius), - DubinsPath.Type.LSR to Pair(-firstCircle.radius, secondCircle.radius), - DubinsPath.Type.LSL to Pair(-firstCircle.radius, -secondCircle.radius) - ) - return buildMap { - for ((route: DubinsPath.Type, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (distance * distance >= r * r) { - val l = sqrt(distance * distance - r * r) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - route, - Tangent( - startCircle = Circle2D(firstCircle.center, firstCircle.radius), - endCircle = secondCircle, - startObstacle = firstObstacle, - endObstacle = secondObstacle, - lineSegment = LineSegment( - firstCircle.center + w * r1, - secondCircle.center + w * r2 - ), - startDirection = route.first, - endDirection = route.third - ) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } -} - -internal class Obstacle( - public val circles: List, -) { - internal val tangents: List = boundaryTangents().first - public val boundaryRoute: DubinsPath.Type = boundaryTangents().second - - public val center: Vector2D = vector( - circles.sumOf { it.center.x } / circles.size, - circles.sumOf { it.center.y } / circles.size - ) - - private fun boundaryTangents(): Pair, DubinsPath.Type> { - // outer tangents for a polygon circles can be either lsl or rsr - - fun Circle2D.dubinsTangentsToCircles( - other: Circle2D, - ): Map = with(Euclidean2DSpace) { - val line = LineSegment(center, other.center) - val d = line.begin.distanceTo(line.end) - val angle1 = atan2(other.center.x - center.x, other.center.y - center.y) - var r: Double - var angle2: Double - val routes = mapOf( - DubinsPath.Type.RSR to Pair(radius, other.radius), - DubinsPath.Type.LSL to Pair(-radius, -other.radius) - ) - return buildMap { - for ((routeType, r1r2) in routes) { - val r1 = r1r2.first - val r2 = r1r2.second - r = if (r1.sign == r2.sign) { - r1.absoluteValue - r2.absoluteValue - } else { - r1.absoluteValue + r2.absoluteValue - } - if (d * d >= r * r) { - val l = (d * d - r * r).pow(0.5) - angle2 = if (r1.absoluteValue > r2.absoluteValue) { - angle1 + r1.sign * atan2(r.absoluteValue, l) - } else { - angle1 - r2.sign * atan2(r.absoluteValue, l) - } - val w = vector(-cos(angle2), sin(angle2)) - put( - routeType, Tangent( - Circle2D(center, radius), - other, - this@Obstacle, - this@Obstacle, - LineSegment( - center + w * r1, - other.center + w * r2 - ), - startDirection = routeType.first, - endDirection = routeType.third - ) - ) - } else { - throw Exception("Circles should not intersect") - } - } - } - } - - val firstCircles = circles - val secondCircles = circles.slice(1..circles.lastIndex) + - circles[0] - val lslTangents = firstCircles.zip(secondCircles) - { a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.LSL]!! } - val rsrTangents = firstCircles.zip(secondCircles) - { a, b -> a.dubinsTangentsToCircles(b)[DubinsPath.Type.RSR]!! } - val center = vector( - circles.sumOf { it.center.x } / circles.size, - circles.sumOf { it.center.y } / circles.size - ) - val lslToCenter = lslTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + - lslTangents.sumOf { it.lineSegment.end.distanceTo(center) } - val rsrToCenter = rsrTangents.sumOf { it.lineSegment.begin.distanceTo(center) } + - rsrTangents.sumOf { it.lineSegment.end.distanceTo(center) } - return if (rsrToCenter >= lslToCenter) { - Pair(rsrTangents, DubinsPath.Type.RSR) - } else { - Pair(lslTangents, DubinsPath.Type.LSL) - } - } - - internal fun nextTangent(circle: Circle2D, direction: Trajectory2D.Direction): Tangent { - if (direction == boundaryRoute.first) { - for (i in circles.indices) { - if (circles[i] == circle) { - return tangents[i] - } - } - } else { - for (i in circles.indices) { - if (circles[i] == circle) { - if (i > 0) { - return Tangent( - circles[i], - circles[i - 1], - this, - this, - LineSegment( - tangents[i - 1].lineSegment.end, - tangents[i - 1].lineSegment.begin - ), - direction - ) - } else { - return Tangent( - circles[0], - circles.last(), - this, - this, - LineSegment( - tangents.last().lineSegment.end, - tangents.last().lineSegment.begin - ), - direction - ) - } - } - } - } - - error("next tangent not found") - } - - override fun equals(other: Any?): Boolean { - if (other == null || other !is Obstacle) return false - return circles == other.circles - } - - override fun hashCode(): Int { - return circles.hashCode() - } -} - -internal fun Obstacle(vararg circles: Circle2D): Obstacle = Obstacle(listOf(*circles)) - -private fun LineSegment2D.intersectSegment(other: LineSegment2D): Boolean { - fun crossProduct(v1: DoubleVector2D, v2: DoubleVector2D): Double { - return v1.x * v2.y - v1.y * v2.x - } - return if (crossProduct(other.begin - begin, other.end - begin).sign == - crossProduct(other.begin - end, other.end - end).sign - ) { - false - } else { - crossProduct(begin - other.begin, end - other.begin).sign != crossProduct( - begin - other.end, - end - other.end - ).sign - } -} - -private fun LineSegment2D.intersectCircle(circle: Circle2D): Boolean { - val a = (begin.x - end.x).pow(2.0) + (begin.y - end.y).pow(2.0) - val b = 2 * ((begin.x - end.x) * (end.x - circle.center.x) + - (begin.y - end.y) * (end.y - circle.center.y)) - val c = (end.x - circle.center.x).pow(2.0) + (end.y - circle.center.y).pow(2.0) - - circle.radius.pow(2.0) - val d = b.pow(2.0) - 4 * a * c - if (d < 1e-6) { - return false - } else { - val t1 = (-b - d.pow(0.5)) * 0.5 / a - val t2 = (-b + d.pow(0.5)) * 0.5 / a - if (((0 < t1) and (t1 < 1)) or ((0 < t2) and (t2 < 1))) { - return true - } - } - return false -} - -private fun Tangent.intersectObstacle(obstacle: Obstacle): Boolean { - for (tangent in obstacle.tangents) { - if (lineSegment.intersectSegment(tangent.lineSegment)) { - return true - } - } - for (circle in obstacle.circles) { - if (lineSegment.intersectCircle(circle)) { - return true - } - } - return false -} - -private fun outerTangents(first: Obstacle, second: Obstacle): Map = buildMap { - for (circle1 in first.circles) { - for (circle2 in second.circles) { - for (tangent in dubinsTangentsToCircles(circle1, circle2, first, second)) { - if (!(tangent.value.intersectObstacle(first)) - and !(tangent.value.intersectObstacle(second)) - ) { - put( - tangent.key, - tangent.value - ) - } - } - } - } -} - -private fun arcLength( - circle: Circle2D, - point1: DoubleVector2D, - point2: DoubleVector2D, - direction: Trajectory2D.Direction, -): Double { - val phi1 = atan2(point1.y - circle.center.y, point1.x - circle.center.x) - val phi2 = atan2(point2.y - circle.center.y, point2.x - circle.center.x) - var angle = 0.0 - when (direction) { - Trajectory2D.L -> { - angle = if (phi2 >= phi1) { - phi2 - phi1 - } else { - 2 * PI + phi2 - phi1 - } - } - - Trajectory2D.R -> { - angle = if (phi2 >= phi1) { - 2 * PI - (phi2 - phi1) - } else { - -(phi2 - phi1) - } - } - } - return circle.radius * angle -} - -private fun normalVectors(v: DoubleVector2D, r: Double): Pair { - return Pair( - r * vector(v.y / norm(v), -v.x / norm(v)), - r * vector(-v.y / norm(v), v.x / norm(v)) - ) -} - -private fun constructTangentCircles( - point: DoubleVector2D, - direction: DoubleVector2D, - r: Double, -): Map { - val center1 = point + normalVectors(direction, r).first - val center2 = point + normalVectors(direction, r).second - val p1 = center1 - point - return if (atan2(p1.y, p1.x) - atan2(direction.y, direction.x) in listOf(PI / 2, -3 * PI / 2)) { - mapOf( - Trajectory2D.L to Circle2D(center1, r), - Trajectory2D.R to Circle2D(center2, r) - ) - } else { - mapOf( - Trajectory2D.L to Circle2D(center2, r), - Trajectory2D.R to Circle2D(center1, r) - ) - } -} - -private fun sortedObstacles( - currentObstacle: Obstacle, - obstacles: List, -): List { - return obstacles.sortedBy { norm(it.center - currentObstacle.center) } -} - -private fun tangentsAlongTheObstacle( - initialCircle: Circle2D, - direction: Trajectory2D.Direction, - finalCircle: Circle2D, - obstacle: Obstacle, -): List { - val dubinsTangents = mutableListOf() - var tangent = obstacle.nextTangent(initialCircle, direction) - dubinsTangents.add(tangent) - while (tangent.endCircle != finalCircle) { - tangent = obstacle.nextTangent(tangent.endCircle, direction) - dubinsTangents.add(tangent) - } - return dubinsTangents -} - -private fun allFinished( - paths: List, - finalObstacle: Obstacle, -): Boolean { - for (path in paths) { - if (path.last().endObstacle != finalObstacle) { - return false - } - } - return true -} - -private fun LineSegment2D.toTrajectory() = StraightTrajectory2D(begin, end) - - -private fun TangentPath.toTrajectory(): CompositeTrajectory2D = CompositeTrajectory2D( - buildList { - tangents.zipWithNext().forEach { (left, right) -> - add(left.lineSegment.toTrajectory()) - add( - CircleTrajectory2D.of( - right.startCircle.center, - left.lineSegment.end, - right.lineSegment.begin, - right.startDirection - ) - ) - } - - add(tangents.last().lineSegment.toTrajectory()) - } -) - -internal fun findAllPaths( - start: DubinsPose2D, - startingRadius: Double, - finish: DubinsPose2D, - finalRadius: Double, - obstacles: List, -): List { - fun DubinsPose2D.direction() = vector(cos(bearing), sin(bearing)) - - val initialCircles = constructTangentCircles( - start, - start.direction(), - startingRadius - ) - val finalCircles = constructTangentCircles( - finish, - finish.direction(), - finalRadius - ) - val trajectories = mutableListOf() - for (i in listOf(Trajectory2D.L, Trajectory2D.R)) { - for (j in listOf(Trajectory2D.L, Trajectory2D.R)) { - val finalCircle = finalCircles[j]!! - val finalObstacle = Obstacle(listOf(finalCircle)) - var currentPaths: List = listOf( - TangentPath( - Tangent( - initialCircles[i]!!, - initialCircles[i]!!, - Obstacle(listOf(initialCircles[i]!!)), - Obstacle(listOf(initialCircles[i]!!)), - LineSegment(start, start), - i - ) - ) - ) - while (!allFinished(currentPaths, finalObstacle)) { - val newPaths = mutableListOf() - for (tangentPath: TangentPath in currentPaths) { - val currentCircle = tangentPath.last().endCircle - val currentDirection: Trajectory2D.Direction = tangentPath.last().endDirection - val currentObstacle = tangentPath.last().endObstacle - var nextObstacle: Obstacle? = null - if (currentObstacle != finalObstacle) { - val tangentToFinal = outerTangents(currentObstacle, finalObstacle)[DubinsPath.Type( - currentDirection, - Trajectory2D.S, - j - )] - for (obstacle in sortedObstacles(currentObstacle, obstacles)) { - if (tangentToFinal!!.intersectObstacle(obstacle)) { - nextObstacle = obstacle - break - } - } - if (nextObstacle == null) { - nextObstacle = finalObstacle - } - val nextTangents: Map = outerTangents(currentObstacle, nextObstacle) - .filter { (key, tangent) -> - obstacles.none { obstacle -> tangent.intersectObstacle(obstacle) } && - key.first == currentDirection && - (nextObstacle != finalObstacle || key.third == j) - } - - var tangentsAlong: List - for (tangent in nextTangents.values) { - if (tangent.startCircle == tangentPath.last().endCircle) { - val lengthMaxPossible = arcLength( - tangent.startCircle, - tangentPath.last().lineSegment.end, - tangent.startObstacle.nextTangent( - tangent.startCircle, - currentDirection - ).lineSegment.begin, - currentDirection - ) - val lengthCalculated = arcLength( - tangent.startCircle, - tangentPath.last().lineSegment.end, - tangent.lineSegment.begin, - currentDirection - ) - tangentsAlong = if (lengthCalculated > lengthMaxPossible) { - tangentsAlongTheObstacle( - currentCircle, - currentDirection, - tangent.startCircle, - currentObstacle - ) - } else { - emptyList() - } - } else { - tangentsAlong = tangentsAlongTheObstacle( - currentCircle, - currentDirection, - tangent.startCircle, - currentObstacle - ) - } - newPaths.add(TangentPath(tangentPath.tangents + tangentsAlong + tangent)) - } - } else { - newPaths.add(tangentPath) - } - } - currentPaths = newPaths - } - - trajectories += currentPaths.map { tangentPath -> - val lastDirection: Trajectory2D.Direction = tangentPath.last().endDirection - val end = finalCircles[j]!! - TangentPath( - tangentPath.tangents + - Tangent( - end, - end, - Obstacle(end), - Obstacle(end), - LineSegment(finish, finish), - startDirection = lastDirection, - endDirection = j - ) - ) - }.map { it.toTrajectory() } - } - } - return trajectories -} - - -public object Obstacles { - public fun allPathsAvoiding( - start: DubinsPose2D, - finish: DubinsPose2D, - trajectoryRadius: Double, - obstaclePolygons: List>, - ): List { - val obstacles: List = obstaclePolygons.map { polygon -> - Obstacle(polygon.points.map { point -> Circle2D(point, trajectoryRadius) }) - } - return findAllPaths(start, trajectoryRadius, finish, trajectoryRadius, obstacles) - } -} - - - - - diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt deleted file mode 100644 index 59a8e613a..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory2D.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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:UseSerializers(Euclidean2DSpace.VectorSerializer::class) - -package space.kscience.kmath.trajectory - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.UseSerializers -import space.kscience.kmath.geometry.* -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import kotlin.math.atan2 - -@Serializable -public sealed interface Trajectory2D { - public val length: Double - - - public sealed interface Type - - public sealed interface Direction: Type - - public object R : Direction { - override fun toString(): String = "R" - } - - public object S : Type { - override fun toString(): String = "L" - } - - public object L : Direction { - override fun toString(): String = "L" - } -} - -/** - * Straight path segment. The order of start and end defines the direction - */ -@Serializable -@SerialName("straight") -public data class StraightTrajectory2D( - override val begin: DoubleVector2D, - override val end: DoubleVector2D, -) : Trajectory2D, LineSegment2D { - - override val length: Double get() = begin.distanceTo(end) - - public val bearing: Angle get() = (atan2(end.x - begin.x, end.y - begin.y).radians).normalized() -} - -/** - * An arc segment - */ -@Serializable -@SerialName("arc") -public data class CircleTrajectory2D( - public val circle: Circle2D, - public val start: DubinsPose2D, - public val end: DubinsPose2D, -) : Trajectory2D { - - /** - * Arc length in radians - */ - val arcLength: Angle - get() = if (direction == Trajectory2D.L) { - start.bearing - end.bearing - } else { - end.bearing - start.bearing - }.normalized() - - - override val length: Double by lazy { - circle.radius * arcLength.radians - } - - public val direction: Trajectory2D.Direction by lazy { - if (start.y < circle.center.y) { - if (start.bearing > Angle.pi) Trajectory2D.R else Trajectory2D.L - } else if (start.y > circle.center.y) { - if (start.bearing < Angle.pi) Trajectory2D.R else Trajectory2D.L - } else { - if (start.bearing == Angle.zero) { - if (start.x < circle.center.x) Trajectory2D.R else Trajectory2D.L - } else { - if (start.x > circle.center.x) Trajectory2D.R else Trajectory2D.L - } - } - } - - public companion object { - public fun of( - center: DoubleVector2D, - start: DoubleVector2D, - end: DoubleVector2D, - direction: Trajectory2D.Direction, - ): CircleTrajectory2D { - fun calculatePose( - vector: DoubleVector2D, - theta: Angle, - direction: Trajectory2D.Direction, - ): DubinsPose2D = DubinsPose2D( - vector, - when (direction) { - Trajectory2D.L -> (theta - Angle.piDiv2).normalized() - Trajectory2D.R -> (theta + Angle.piDiv2).normalized() - } - ) - - val s1 = StraightTrajectory2D(center, start) - val s2 = StraightTrajectory2D(center, end) - val pose1 = calculatePose(start, s1.bearing, direction) - val pose2 = calculatePose(end, s2.bearing, direction) - val trajectory = CircleTrajectory2D(Circle2D(center, s1.length), pose1, pose2) - if (trajectory.direction != direction) error("Trajectory direction mismatch") - return trajectory - } - } -} - -@Serializable -@SerialName("composite") -public class CompositeTrajectory2D(public val segments: List) : Trajectory2D { - override val length: Double get() = segments.sumOf { it.length } -} - -public fun CompositeTrajectory2D(vararg segments: Trajectory2D): CompositeTrajectory2D = - CompositeTrajectory2D(segments.toList()) - diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt deleted file mode 100644 index 80f7173f1..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/DubinsTests.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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 space.kscience.kmath.geometry.equalsFloat -import kotlin.test.Test -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - - -class DubinsTests { - - @Test - fun dubinsTest() = with(Euclidean2DSpace){ - val straight = StraightTrajectory2D(vector(0.0, 0.0), vector(100.0, 100.0)) - val lineP1 = straight.shift(1, 10.0).inverse() - - val start = DubinsPose2D(straight.end, straight.bearing) - val end = DubinsPose2D(lineP1.begin, lineP1.bearing) - 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 -> DubinsPath.trajectoryTypeOf(p) == it.key } - assertNotNull(path, "Path ${it.key} not found") - println("${it.key}: ${path.length}") - assertTrue(it.value.equalsFloat(path.length)) - - val a = path.segments[0] as CircleTrajectory2D - val b = path.segments[1] - val c = path.segments[2] as CircleTrajectory2D - - assertTrue(start.equalsFloat(a.start)) - assertTrue(end.equalsFloat(c.end)) - - // Not working, theta double precision inaccuracy - if (b is CircleTrajectory2D) { - assertTrue(a.end.equalsFloat(b.start)) - assertTrue(c.start.equalsFloat(b.end)) - } else if (b is StraightTrajectory2D) { - assertTrue(a.end.equalsFloat(DubinsPose2D(b.begin, b.bearing))) - assertTrue(c.start.equalsFloat(DubinsPose2D(b.end, b.bearing))) - } - } - } -} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt deleted file mode 100644 index 1a8c3a474..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/ObstacleTest.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.vector -import kotlin.test.Test -import kotlin.test.assertEquals - -class ObstacleTest { - @Test - fun firstPath() { - val startPoint = vector(-5.0, -1.0) - val startDirection = vector(1.0, 1.0) - val startRadius = 0.5 - val finalPoint = vector(20.0, 4.0) - val finalDirection = vector(1.0, -1.0) - val finalRadius = 0.5 - - val obstacles = listOf( - Obstacle( - listOf( - Circle2D(vector(7.0, 1.0), 5.0) - ) - ) - ) - - val outputTangents = findAllPaths( - DubinsPose2D.of(startPoint, startDirection), - startRadius, - DubinsPose2D.of(finalPoint, finalDirection), - finalRadius, - obstacles - ) - val length = outputTangents.minOf { it.length } - assertEquals(27.2113183, length, 1e-6) - } - - @Test - fun secondPath() { - val startPoint = vector(-5.0, -1.0) - val startDirection = vector(1.0, 1.0) - val startRadius = 0.5 - val finalPoint = vector(20.0, 4.0) - val finalDirection = vector(1.0, -1.0) - val finalRadius = 0.5 - - val obstacles = listOf( - Obstacle( - listOf( - Circle2D(vector(1.0, 6.5), 0.5), - Circle2D(vector(2.0, 1.0), 0.5), - Circle2D(vector(6.0, 0.0), 0.5), - Circle2D(vector(5.0, 5.0), 0.5) - ) - ), Obstacle( - listOf( - Circle2D(vector(10.0, 1.0), 0.5), - Circle2D(vector(16.0, 0.0), 0.5), - Circle2D(vector(14.0, 6.0), 0.5), - Circle2D(vector(9.0, 4.0), 0.5) - ) - ) - ) - val paths = findAllPaths( - DubinsPose2D.of(startPoint, startDirection), - startRadius, - DubinsPose2D.of(finalPoint, finalDirection), - finalRadius, - obstacles - ) - val length = paths.minOf { it.length } - assertEquals(28.9678224, length, 1e-6) - } - - @Test - fun equalObstacles() { - val circle1 = Circle2D(vector(1.0, 6.5), 0.5) - val circle2 = Circle2D(vector(1.0, 6.5), 0.5) - assertEquals(circle1, circle2) - val obstacle1 = Obstacle(listOf(circle1)) - val obstacle2 = Obstacle(listOf(circle2)) - assertEquals(obstacle1, obstacle2) - } -} \ No newline at end of file diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt deleted file mode 100644 index 2ae89038c..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/TangentTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2018-2023 KMath 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.vector -import space.kscience.kmath.geometry.LineSegment -import space.kscience.kmath.geometry.equalsLine -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertTrue - -class TangentTest { - @Test - fun tangents() { - val c1 = Circle2D(vector(0.0, 0.0), 1.0) - val c2 = Circle2D(vector(4.0, 0.0), 1.0) - val routes = listOf( - DubinsPath.Type.RSR, - DubinsPath.Type.RSL, - DubinsPath.Type.LSR, - DubinsPath.Type.LSL - ) - val segments = listOf( - LineSegment( - begin = vector(0.0, 1.0), - end = vector(4.0, 1.0) - ), - LineSegment( - begin = vector(0.5, 0.8660254), - end = vector(3.5, -0.8660254) - ), - LineSegment( - begin = vector(0.5, -0.8660254), - end = vector(3.5, 0.8660254) - ), - LineSegment( - begin = vector(0.0, -1.0), - end = vector(4.0, -1.0) - ) - ) - - val tangentMap = c1.tangentsToCircle(c2) - val tangentMapKeys = tangentMap.keys.toList() - val tangentMapValues = tangentMap.values.toList() - - assertEquals(routes, tangentMapKeys) - for (i in segments.indices) { - assertTrue(segments[i].equalsLine(Euclidean2DSpace, tangentMapValues[i])) - } - } - - @Test - fun concentric(){ - val c1 = Circle2D(vector(0.0, 0.0), 10.0) - val c2 = Circle2D(vector(0.0, 0.0), 1.0) - assertEquals(emptyMap(), c1.tangentsToCircle(c2)) - } -} \ No newline at end of file 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 deleted file mode 100644 index 8b8ccf95e..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/math.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 space.kscience.kmath.geometry.equalsFloat -import space.kscience.kmath.geometry.radians -import space.kscience.kmath.geometry.sin - - -fun DubinsPose2D.equalsFloat(other: DubinsPose2D) = - x.equalsFloat(other.x) && y.equalsFloat(other.y) && bearing.radians.equalsFloat(other.bearing.radians) - -fun StraightTrajectory2D.inverse() = StraightTrajectory2D(end, begin) - -fun StraightTrajectory2D.shift(shift: Int, width: Double): StraightTrajectory2D = with(Euclidean2DSpace) { - val dX = width * sin(inverse().bearing) - val dY = width * sin(bearing) - - return StraightTrajectory2D( - vector(begin.x - dX * shift, begin.y - dY * shift), - vector(end.x - dX * shift, end.y - dY * shift) - ) -} 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 deleted file mode 100644 index b3825b93b..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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.geometry.degrees -import space.kscience.kmath.trajectory.CircleTrajectory2D -import space.kscience.kmath.trajectory.Trajectory2D -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 = CircleTrajectory2D.of( - circle.center, - vector(-2.0, 0.0), - vector(0.0, 2.0), - Trajectory2D.R - ) - assertEquals(circle.circumference / 4, arc.length, 1.0) - assertEquals(0.0, arc.start.bearing.degrees) - assertEquals(90.0, arc.end.bearing.degrees) - } -} 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 deleted file mode 100644 index c3fca06ec..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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 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, 1e-4) - } -} 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 deleted file mode 100644 index 54deb2193..000000000 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018-2022 KMath 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.geometry.degrees -import space.kscience.kmath.trajectory.StraightTrajectory2D -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 = StraightTrajectory2D(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.bearing.degrees) - } - - @Test - fun lineAngleTest() = with(Euclidean2DSpace){ - //val zero = Vector2D(0.0, 0.0) - val north = StraightTrajectory2D(zero, vector(0.0, 2.0)) - assertEquals(0.0, north.bearing.degrees) - val east = StraightTrajectory2D(zero, vector(2.0, 0.0)) - assertEquals(90.0, east.bearing.degrees) - val south = StraightTrajectory2D(zero, vector(0.0, -2.0)) - assertEquals(180.0, south.bearing.degrees) - val west = StraightTrajectory2D(zero, vector(-2.0, 0.0)) - assertEquals(270.0, west.bearing.degrees) - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 7d92dc36e..f158f3444 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,7 +44,6 @@ include( ":kmath-jupyter", ":kmath-symja", ":kmath-jafama", - ":kmath-trajectory", ":examples", ":benchmarks", )